Quy cách về ngôn ngữ

Trang này chỉ định Ngôn ngữ định nghĩa giao diện dịch vụ xe (VSIDL) bằng cách sử dụng Biểu mẫu Backus-Naur mở rộng (EBNF) ISO/IEC 14977 và protobuf. Trang này tập trung vào ngữ pháp không theo ngữ cảnh của ngôn ngữ và ý nghĩa của các phần tử ngôn ngữ.

Hệ phân cấp ngôn ngữ

Theo Cơ sở đối tượng meta (MOF), trình biên dịch VSIDL (VSIDLC) sử dụng các ngôn ngữ được minh hoạ trong Hình 1:

Ngôn ngữ VSIDLC

Hình 1. Các ngôn ngữ VSIDLC.

VSIDLC chủ yếu dựa trên ngôn ngữ vùng đệm giao thức (protobuf). Protobuf được dùng để chỉ định các kiểu dữ liệu được trao đổi bằng cách sử dụng các lệnh gọi đăng ký-xuất bản và lệnh gọi quy trình từ xa (RPC). Theo quan điểm kỹ thuật, các mô hình VSIDL là tệp TextProto, trong đó cú pháp của VSIDL được xác định trong tệp protobuf (syntax.proto). Cả tệp protobuf để chỉ định kiểu dữ liệu và mô hình VSIDL đều được dùng để tạo mã Rust. Mã được tạo chủ yếu chứa các cấu trúc triển khai cấu trúc dữ liệu cho các thông báo được trao đổi và các hàm Rust triển khai các hàm để tạo đơn vị dịch vụ trong Rust, mà không tự động gọi các đơn vị dịch vụ này. Mã Rust được tạo này đi kèm với mã Rust tuỳ chỉnh sử dụng mã được tạo để tạo thực thể cho các đơn vị dịch vụ và triển khai logic nghiệp vụ của ứng dụng.

Cú pháp trừu tượng

Hình 2 cho thấy các loại thông báo chính trong VSIDL:

Các loại thông báo cốt lõi trong VSIDL

Hình 2. Các loại thông báo chính trong VSIDL.

Mục nhập VSIDL

Phần này giải thích loại thông báo mục nhập VSIDL.

Ngữ pháp EBNF

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

Định nghĩa 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;
}

Ví dụ về cách sử dụng

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

service_bundle {
  name: "Manager"

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

Giải thích

Thông báo VsidlEntry đóng vai trò là vùng chứa gốc cho tệp VSIDL (có đuôi .vsidl). Thông báo này đóng gói tất cả các định nghĩa và cấu hình trong một tệp VSIDL. VsidlEntry là phần tử cấp cao nhất liên kết mọi thứ khác.

Mục đích:

  • Xác định cấu trúc tổng thể của tệp VSIDL.
  • Chỉ định không gian tên gói cho tất cả các thực thể trong tệp.
  • Chứa một tập hợp các định nghĩa gói dịch vụ.
  • Cho phép các phần mở rộng tuỳ chỉnh cho mô hình VSIDL.
  • Bao gồm các quy tắc ánh xạ cho SOME/IP và VHAL.

Giới hạn

  • Tên gói (E211): Tên gói không được vượt quá 127 ký tự.
  • Tệp bị treo (E10B): Tất cả các tệp trong danh mục phải được tham chiếu trong một nhóm tệp Android.bp.

Gói dịch vụ

Phần này giải thích loại thông báo gói dịch vụ.

Ngữ pháp 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
;

Định nghĩa 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;
}

Ví dụ về cách sử dụng

service_bundle {
    name: "SeatController"

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

Giải thích

Gói dịch vụ xác định nhóm logic của các dịch vụ, nhà xuất bản, người đăng ký, máy chủ RPC và ứng dụng RPC có liên quan. Gói dịch vụ hoạt động như một vùng chứa cho một tập hợp chức năng cụ thể và các lượt tương tác của chúng.

Giới hạn

  • Yêu cầu về tên gói (E209, E20A, E20B, E20C):
    • Gói dịch vụ phải có tên được điền sẵn.
    • Tên phải bắt đầu bằng một ký tự bắt đầu giá trị nhận dạng Unicode hợp lệ (thường là một chữ cái).
    • Các ký tự tiếp theo trong tên phải là các ký tự tiếp tục giá trị nhận dạng Unicode hợp lệ (thường là chữ cái hoặc số).
    • Tên không được là từ khoá dành riêng trong Rust, Java hoặc C++.
  • Tính duy nhất của gói toàn cầu (E309): Mọi gói dịch vụ phải có tên đủ điều kiện duy nhất (dựa trên gói và tên của gói).
  • Tính duy nhất nội bộ (E100, E300, E302, E303, E308):
    • Trong một gói dịch vụ duy nhất, mỗi dịch vụ RPC có thể được phân phát tối đa một định nghĩa máy chủ.
    • Trong một gói dịch vụ duy nhất, mỗi loại xuất bản MULTI_PUB có thể được xuất bản tối đa một định nghĩa nhà xuất bản.
    • Trong một gói dịch vụ duy nhất, tất cả tên đơn vị dịch vụ do người dùng xác định (cho nhà xuất bản hoặc máy chủ) phải là duy nhất.
    • Trong một gói dịch vụ duy nhất, tất cả tên đơn vị dịch vụ (dù do người dùng xác định hay được tạo tự động) phải là duy nhất.
  • Quy ước đặt tên mục tiêu bản dựng (E205, E206, E207, E208): Nếu tên mục tiêu bản dựng tuỳ chỉnh (build_cfg.target_name) được cung cấp, thì tên đó phải tuân thủ định dạng snake case (chữ cái viết thường, số và dấu gạch dưới đơn, không bắt đầu hoặc kết thúc bằng dấu gạch dưới).
  • Tính duy nhất của tên mục tiêu bản dựng (E301): Tên mục tiêu bản dựng do người dùng xác định không được xung đột với bất kỳ tên mục tiêu nào được tạo tự động cho các gói dịch vụ khác.

Publisher

Phần này giải thích loại thông báo Nhà xuất bản.

Ngữ pháp EBNF

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

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

Định nghĩa 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;
}

Ví dụ về cách sử dụng

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

Giải thích

Loại thông báo Publisher xác định nguồn dữ liệu mà ServiceBundle cung cấp. Loại thông báo này chỉ định loại dữ liệu đang được xuất bản và các chủ đề cụ thể cũng như dung lượng của dữ liệu đó.

Chủ đề

Mỗi thực thể Publisher có một trường message tham chiếu đến thông báo proto đang được xuất bản. Trường này phải chỉ định một chủ đề (được biểu thị bằng topic) và dung lượng (được biểu thị bằng capacity).

  • Chủ đề: Giá trị nhận dạng duy nhất cho chủ đề xuất bản. Trường này phải tuân theo định dạng dash-case viết thường (ví dụ: my-topic).
  • Dung lượng: Chỉ định kích thước của hàng đợi, tức là số lượng thông báo mà hàng đợi có thể chứa trước khi các thông báo chưa đọc bị loại bỏ. Trường này phải là một số chẵn lớn hơn hoặc bằng 2.

Tên do người dùng xác định

Nhà xuất bản có thể có tên đơn vị dịch vụ do người dùng xác định để ghi đè tên đơn vị dịch vụ được chọn tự động. Khả năng này cho phép chọn tên ngắn hơn. Nếu nhà xuất bản sử dụng tên đơn vị dịch vụ do người dùng xác định, thì nhà xuất bản đó có thể chỉ sử dụng một thực thể duy nhất để tên đơn vị dịch vụ được gán duy nhất cho một thực thể.

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

Giới hạn

  • Vị trí nhà xuất bản (E300): Nhà xuất bản cho cùng một loại MULTI_PUB phải được xác định trong các gói dịch vụ riêng biệt.
  • Tính duy nhất của tên cục bộ (E302): Trong bất kỳ gói dịch vụ nào, tất cả nhà xuất bản phải có tên đơn vị dịch vụ do người dùng xác định duy nhất.
  • Tính duy nhất của tên toàn cầu (E304): Nhà xuất bản của cùng một loại ấn phẩm phải có tên đơn vị dịch vụ do người dùng xác định duy nhất trên toàn cầu trên tất cả các gói dịch vụ.
  • Đặt tên cho các kênh đơn (E306): Tên đơn vị dịch vụ do người dùng xác định chỉ có thể được gán cho các nhà xuất bản xử lý chính xác một thực thể.
  • Giới hạn nhà xuất bản đơn (E307): Thông báo protobuf được đánh dấu là SINGLE_PUB chỉ có thể được xuất bản bởi một nhà xuất bản trên toàn bộ hệ thống.
  • Tính duy nhất của tên đơn vị dịch vụ (E308): Tất cả tên đơn vị dịch vụ (dù được tạo hay do người dùng xác định) phải là duy nhất trong gói dịch vụ của chúng; tên do người dùng xác định nên được dùng để giải quyết xung đột với tên được tạo.
  • Yêu cầu về thông số biến thể (E501): Khi nhà xuất bản sử dụng tên do người dùng xác định cho một loại có nhiều biến thể, nhà xuất bản đó phải chỉ định rõ biến thể mà nhà xuất bản đó xuất bản.
  • Sự tồn tại của nhà xuất bản đối với người đăng ký (E504): Mọi người đăng ký được xác định đều yêu cầu ít nhất một nhà xuất bản tương ứng cho loại và biến thể được chỉ định.
  • Loại nhà xuất bản hợp lệ (E601): Nhà xuất bản phải tham chiếu đến một loại tương ứng với thông báo protobuf hiện có.
  • Yêu cầu về chú thích xuất bản (E602): Loại thông báo protobuf được nhà xuất bản tham chiếu phải bao gồm chú thích SdvPublication.
  • Cách sử dụng biến thể hợp lệ (E606): Nếu nhà xuất bản chỉ định một biến thể (thực thể), thì biến thể đó phải tồn tại trong instances_enum được xác định cho loại xuất bản trong protobuf.
  • Điều kiện chỉ định biến thể (E607): Nhà xuất bản chỉ có thể chỉ định một biến thể (thực thể) rõ ràng nếu loại xuất bản xác định instances_enum trong protobuf.
  • Đặt tên chủ đề (E20D, E20F): Chủ đề phải ở định dạng dash-case viết thường và không được vượt quá 127 ký tự.
  • Tính duy nhất của chủ đề (E314): Chủ đề phải là duy nhất trên toàn cầu trên tất cả các nhà xuất bản.
  • Yêu cầu về dung lượng (E406, E407): Dung lượng là bắt buộc và phải là số chẵn >= 2.

Người đăng ký

Phần này giải thích loại thông báo Người đăng ký.

Ngữ pháp EBNF

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

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

Định nghĩa 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;
}

Ví dụ về cách sử dụng

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

Giải thích

Thông báo Subscriber xác định một trình nhận xuất bản mà ServiceBundle cung cấp. Thông báo này chỉ định loại dữ liệu đang được đăng ký và các chủ đề cụ thể của ấn phẩm đó. Nếu có nhiều nhà xuất bản cho một chủ đề, thì người đăng ký sẽ nhận được các thông báo do tất cả nhà xuất bản đó xuất bản.

Giới hạn

  • Sự tồn tại của nhà xuất bản (E504): Đối với mỗi người đăng ký được xác định, phải có ít nhất một nhà xuất bản tương ứng xuất bản loại và biến thể xuất bản được chỉ định.
  • Loại đăng ký hợp lệ (E608): Người đăng ký phải tham chiếu đến một loại tương ứng với thông báo protobuf hiện có được xác định bằng chú thích SdvPublication.
  • Đăng ký biến thể hợp lệ (E609): Nếu người đăng ký chỉ định một biến thể (thực thể), thì biến thể đó phải là giá trị hợp lệ được xác định trong instances_enum của loại xuất bản protobuf tương ứng.
  • Chủ đề bắt buộc (E408): Chủ đề là bắt buộc đối với người đăng ký.
  • Khai báo lại chủ đề (E311): Chủ đề của người đăng ký không được khai báo lại trong cùng một gói dịch vụ.

Máy chủ RPC

Phần này giải thích loại thông báo máy chủ RPC.

Ngữ pháp EBNF

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

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

Định nghĩa 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;
}

Ví dụ về cách sử dụng

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

Giải thích

Thông báo Server xác định máy chủ RPC mà ServiceBundle cung cấp. Thông báo này chỉ định dịch vụ mà máy chủ triển khai và kênh RPC.

Máy chủ RPC hiển thị một tập hợp các phương thức mà ứng dụng có thể gọi từ xa. Trường service chỉ định tên của dịch vụ RPC mà máy chủ triển khai. Dịch vụ này được xác định trong tệp proto và được triển khai trong mã Rust tuỳ chỉnh. Các dịch vụ RPC có thể bao gồm các phương thức đơn nguyên, truyền trực tuyến phía ứng dụng và truyền trực tuyến phía máy chủ, như được xác định trong định nghĩa dịch vụ protobuf. Trường channel xác định điểm cuối giao tiếp và là bắt buộc (E409).

Giới hạn

  • Định nghĩa dịch vụ (E603): Máy chủ RPC phải chỉ định giá trị service tương ứng với giá trị service RPC protobuf hiện có.
  • Giới hạn máy chủ cho mỗi dịch vụ (E100): Trong một gói dịch vụ duy nhất, một service RPC cụ thể có thể được phân phát tối đa một định nghĩa máy chủ.
  • Đặt tên kênh (E20E): Kênh RPC phải ở định dạng dash-case viết thường.
  • Kênh bắt buộc (E409): Kênh RPC là bắt buộc.
  • Tính duy nhất của kênh (E40B): Kênh RPC chỉ được dùng bởi một dịch vụ.

Ứng dụng RPC

Phần này giải thích loại thông báo ứng dụng RPC.

Ngữ pháp EBNF

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

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

Định nghĩa 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;
}

Ví dụ về cách sử dụng

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

Giải thích

client xác định ứng dụng RPC mà ServiceBundle sử dụng. client chỉ định dịch vụ mà ứng dụng tương tác và kênh để kết nối. Ứng dụng có thể tương tác với các phương thức đơn nguyên, truyền trực tuyến phía ứng dụng và truyền trực tuyến phía máy chủ, tuỳ thuộc vào định nghĩa dịch vụ.

Giới hạn

  • Định nghĩa dịch vụ (E60A): Ứng dụng RPC phải chỉ định service tương ứng với định nghĩa service protobuf hiện có.
  • Nguồn dịch vụ duy nhất (E60B): Định nghĩa service protobuf được service của ứng dụng RPC tham chiếu phải được xác định duy nhất (không được xác định nhiều lần) trên tất cả các tệp protobuf.
  • Kênh bắt buộc (E409): Kênh RPC là bắt buộc.

Cấu hình bản dựng

Phần này giải thích loại thông báo Cấu hình bản dựng.

Ngữ pháp EBNF

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

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

Định nghĩa 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;
}

Ví dụ về cách sử dụng

build_cfg {
  target_name: "my_custom_target_name"
  skip_codegen: false
}

Giải thích

BuildConfiguration định cấu hình các tham số không chuẩn của ServiceBundle để tạo mã. Tất cả cấu hình bản dựng đều không bắt buộc.

  • target_name (string không bắt buộc): Chỉ định tên của mục tiêu bản dựng trong tệp Android.bp. Sử dụng tham số này để đặt tên mục tiêu bằng tên ngắn hơn tên được chọn tự động.
  • skip_codegen (bool không bắt buộc): Cho biết có nên bỏ qua quá trình tạo mã cho gói dịch vụ này hay không. Nếu được đặt thành true, thì không cần mã nào được tạo cho gói dịch vụ cụ thể này. Tham số này có thể hữu ích cho các gói dịch vụ được triển khai theo cách thủ công. Theo mặc định, tham số này được đặt thành false.

Giới hạn

  • Định dạng tên mục tiêu (E205, E206, E207, E208): Nếu tên mục tiêu bản dựng tuỳ chỉnh (build_cfg.target_name) được cung cấp, thì tên đó phải tuân thủ nghiêm ngặt định dạng snake case:
    • Tên này chỉ được chứa chữ cái viết thường (a đến z), số (0 đến 9) và dấu gạch dưới (_).
    • Tên này không được chứa các dấu gạch dưới liên tiếp (__).
    • Tên này không được bắt đầu bằng dấu gạch dưới.
    • Tên này không được kết thúc bằng dấu gạch dưới.
  • Tính duy nhất của tên mục tiêu (E301): build_cfg.target_name do người dùng xác định phải là duy nhất trên hệ thống xây dựng và không được xung đột với bất kỳ tên mục tiêu nào được tạo tự động bắt nguồn từ các định nghĩa gói dịch vụ khác.