VSIDL 提供程序是一组库和工具,可让服务软件包向 SDV 平台代理(诊断、遥测和 SOME/IP)提供 VSIDL 声明的元数据。
具体来说,VSIDL 提供程序可让 SDV 代理发现以下元数据:
- VSIDL 目录中使用的消息和服务的 protobuf 描述符
- SOME/IP 映射
- 服务包的诊断声明
面向服务软件包开发者的 VSIDL 提供方指南
VSIDL 提供程序库执行以下操作。
- 在两个特定位置查找文件:
- 位于 sdv_service_bundle_metadata 中定义的路径中的 Apex 内。
- 在静态路径中的映像上。
- 发起 RPC 调用,以查询位于相同或不同虚拟机上的代理的 API。
如果您正在开发服务软件包,则无需了解 VSIDL 提供程序库的具体细节。您只需按照以下步骤操作,即可使 VSIDL 提供程序在运行时找到所需的文件。
为目录生成运行时配置
这三种类型的文件(VSIDL 架构、诊断声明、SOME/IP 映射)均由 vsidl_rc_generator 工具生成。
使用 vsidl_rc_generator 主机二进制工具,并使用与 vsidlc 相同的参数以及以下其他参数:
--variant runtime-config-prebuilts--filegroup来指定包含目录的所有文件(包括Android.bp)的文件组目标名称。
相关 vsidlc 参数如下,供参考:
--catalog-path用于指定目录的根路径。--dependency-catalog-path来指定相关联的目录。-- -path用于指定将包含所有生成的genrule和prebuilt_etc目标的Android.bp写入何处。
生成器将创建一个包含相关 genrule 和 prebuilt_etc 目标的 Android.bp 文件。在 Android.bp 中生成的各个目标块之上,会有注释指明相应目标的预期用途。
更新 APEX 的 Android.bp
如生成的 Android.bp 文件的注释所示,该文件内容如下:
// Usage: add the following line to ... declaration
您应将这些目标(在指示的 Usage 注释下方)添加到定义 Apex 的 Android.bp 中:
apex {
name: "some_apex_name",
...
prebuilts: [
// ADD THE prebuilt_etc TARGETS HERE
],
...
}
更新 APEX 的 sdv_service_bundles_manifest.textproto
在 APEX 的 sdv_service_bundles_manifest.textproto 文件的 sdv_service_bundle_metadata 块中,您需要定义(仅适用于相关路径):
sdv_service_bundle_metadata {
...
vsidl_schemas_path: "etc/vsidl_provider/SomeFile-vsidl-config.binpb"
diagnostics_config_path: "etc/vsidl_provider/SomeFile-diag-config.binpb"
external_protocol_mapping_path: "etc/vsidl_provider/someip-config.binpb"
...
}
请勿定义自己的路径。请改为复制生成的 Android.bp 文件注释中显示的路径,如下所示:
// + vsidl_schemas_path:
// + diagnostics_config_path:
// + external_protocol_mapping_path:
这样做可使 VSIDL 提供程序实例能够从相应 sdv_service_bundle_metadata 条目中指定的路径进行查询。
向图片添加目标
生成的 Android.bp 文件还会生成可直接加载到图片上的目标。注释还通过以下方式指明了应以这种方式使用的目标平台:
// Usage: add this target to the VM image.
生成的 prebuilt_etc 目标会将使用 genrule 生成的文件放置在映像上的预先指定的位置。您需要在相应的 *.mk 文件(例如 device/google/sdv/sdv_core_base/sdv_samples_automotive_services.mk)中添加 prebuilt_etc 目标。
面向平台开发者的 VSIDL 提供方指南
一般来说,如果您正在开发需要反射功能的 SDV Agent,可以使用 VSIDL 提供程序库。
VSIDL 提供程序库 API 包含以下函数:
async fn get_publication_descriptor(
&self,
source_fqin: &ServiceFqin,
unit_type: &UnitType,
) -> SdvResult<PublicationDescriptor>;
async fn get_rpc_method_descriptor(
&self,
source_fqin: &ServiceFqin,
unit_type: &UnitType,
method_name: &str,
) -> SdvResult<RpcMethodDescriptor>;
async fn get_message_descriptor(
&self,
source_fqin: &ServiceFqin,
message_name: &str,
) -> SdvResult<MessageDescriptor>;
async fn get_someip_mappings(&self, source_fqin: &ServiceFqin)
-> SdvResult<Vec<SomeIpMapping>>;
async fn get_diagnostics_declaration(
&self,
fqin: &ServiceFqin,
) -> SdvResult<DiagnosticsDeclaration>;
async fn subscribe_availability_change_by_vm(
&self,
vm_name: &str,
) -> SdvResult<AvailabilityStream>;
其中
pub type AvailabilityStream = Pin<Box<dyn Stream<Item = AvailabilityChangeEvent> + Send>>;
所有函数都是使用 source_fqin 参数进行查询的。这样可确保使用相同 unit_type 或 message_name 的不同 FQIN 返回正确的数据。该参数指示 VSIDL 提供程序库指向包含最准确消息架构的特定 APEX。这是必需的,因为 APEX 会独立更新,并且可能会针对同一 protobuf 消息或服务使用不同的架构。
get_message_descriptor 函数的用法
这会纯粹返回用于反射的外部箱的 pub struct MessageDescriptor。MessageDescriptor 是一段元数据,可用于反射,从而在运行时动态检查和操控 protobuf 消息。
get_publication_descriptor 函数的用法
此函数会返回一个 PublicationDescriptor,即:
pub struct PublicationDescriptor {
/// Message descriptor for publication.
pub message_descriptor: MessageDescriptor,
/// Information about the size of the publication message.
pub size_metadata: SizeMetadata,
}
size_metadata 字段包含有关发布消息的大小和限制的信息。此元数据源自 VSIDL 配置。
pub struct SizeMetadata {
/// Message size in bytes.
pub message_size: u32,
/// Message count.
pub message_count: u32,
/// VSIDL-declared size constraints for the message fields.
pub field_size_constraints: HashMap<String, FieldSizeConstraint>,
}
pub struct FieldSizeConstraint {
/// Max number of repeated fields allowed for the field.
pub repeated_max_count: Option<u32>,
/// Max size of variable sized types (string, bytes) in bytes.
pub variable_type_max_size: Option<u32>,
}
get_rpc_method_descriptor 函数的用法
此函数会返回一个 RpcMethodDescriptor,即:
pub struct RpcMethodDescriptor {
/// Message descriptor for RPC request.
pub request_message: Option<MessageDescriptor>,
/// Message descriptor for RPC response.
pub response_message: Option<MessageDescriptor>,
}
此结构体包含 RPC 方法的请求和响应消息的 MessageDescriptor。
get_someip_mappings 函数的用法
此函数用于检索在 core_services/vsidl/protos/sdv/someip/v1/someip.proto 中定义的本地 SOME/IP 服务映射。
get_diagnostics_declaration 函数的使用
此函数用于检索诊断声明,这些声明在 core_services/vsidl/protos/sdv/diagnostics/v1/diagnostics_syntax.proto 中定义
subscribe_availability_change_by_vm 函数的用法
此函数会返回指定虚拟机的可用性流,用作关键的回退机制。当标准 VSIDL 提供程序 API 调用失败并出现 SdvStatusCode::Unavailable 错误时,使用此方法可让系统高效地等待 VSIDL 提供程序接口重新上线。
此功能的主要行为包括:
- 立即发出:订阅后,该流会立即发出目标虚拟机的当前可用性状态。
- 行为对等:生成的流的行为与
ServiceDiscoveryManager使用的subscribe_service_unit_change_by_name函数完全相同。
VSIDL 提供方代理
每个虚拟机都在运行自己的 VSIDL 提供程序代理,该代理本质上是一个 RPC 服务器,用于转发 VSIDL 提供程序 API(代理内库的本地实例)上的请求。该代理用于查询不同虚拟机上的 VSIDL 提供程序,也就是说,一个虚拟机上的服务可以使用该代理查询另一个虚拟机上的 VSIDL 元数据。
代码库中 API 的使用情况
SOMEIP:
get_publication_descriptor(使用所有结构体字段)get_rpc_method_descriptor(使用所有结构体字段)get_someip_mappings
遥测:
get_publication_descriptor(仅使用message_descriptor字段)get_rpc_method_descriptor(使用所有结构体字段)
诊断:
get_message_descriptorget_diagnostics_declaration
如需了解各种风味以及各种数据源和来源优先级,请参阅 core_services/vsidl/provider/src/vsidl_provider.rs。
vsidl_provider 箱提供了多个公共函数,用于创建针对不同 SDV 代理量身定制的提供方实例。每项配置都指定了用于解析 VSIDL 相关数据的唯一数据源链。下表概述了每个构造函数的功能:
| 构造函数 | 数据类型 | 数据源查找(和顺序) |
|---|---|---|
new_for_vsidl_provider_agent |
SomeIp | APEX |
Diagnostics | APEX | |
VsidlSchemas | APEX、文件 | |
new_for_diagnostics_agent | Diagnostics | 代理(远程)、APEX |
VsidlSchemas | 文件 | |
new_for_someip_broker_agent |
SomeIp | APEX |
VsidlSchemas | 文件 | |
new_for_telemetry_agent | VsidlSchemas | 代理(远程和本地) |
new_for_integration_test |
SomeIp | 代理(远程和本地) |
Diagnostics | 代理(远程和本地) | |
VsidlSchemas | 代理(远程和本地) |
表格的数据源是指图 1 中的调用。