用于反射的 VSIDL 提供程序

VSIDL 提供程序是一组库和工具,可让服务软件包向 SDV 平台代理(诊断、遥测和 SOME/IP)提供 VSIDL 声明的元数据。

具体来说,VSIDL 提供程序可让 SDV 代理发现以下元数据:

面向服务软件包开发者的 VSIDL 提供方指南

VSIDL 提供程序库执行以下操作。

  • 在两个特定位置查找文件:
    • 位于 sdv_service_bundle_metadata 中定义的路径中的 Apex 内。
    • 在静态路径中的映像上。
  • 发起 RPC 调用,以查询位于相同或不同虚拟机上的代理的 API。

图 1.VSIDL 提供商概览。

如果您正在开发服务软件包,则无需了解 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 用于指定将包含所有生成的 genruleprebuilt_etc 目标的 Android.bp 写入何处。

生成器将创建一个包含相关 genruleprebuilt_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_typemessage_name 的不同 FQIN 返回正确的数据。该参数指示 VSIDL 提供程序库指向包含最准确消息架构的特定 APEX。这是必需的,因为 APEX 会独立更新,并且可能会针对同一 protobuf 消息或服务使用不同的架构。

get_message_descriptor 函数的用法

这会纯粹返回用于反射的外部箱的 pub struct MessageDescriptorMessageDescriptor 是一段元数据,可用于反射,从而在运行时动态检查和操控 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_descriptor
  • get_diagnostics_declaration

如需了解各种风味以及各种数据源和来源优先级,请参阅 core_services/vsidl/provider/src/vsidl_provider.rs

vsidl_provider 箱提供了多个公共函数,用于创建针对不同 SDV 代理量身定制的提供方实例。每项配置都指定了用于解析 VSIDL 相关数据的唯一数据源链。下表概述了每个构造函数的功能:

构造函数数据类型数据源查找(和顺序)
new_for_vsidl_provider_agent SomeIpAPEX
DiagnosticsAPEX
VsidlSchemasAPEX、文件
new_for_diagnostics_agentDiagnostics代理(远程)、APEX
VsidlSchemas文件
new_for_someip_broker_agent SomeIpAPEX
VsidlSchemas文件
new_for_telemetry_agentVsidlSchemas代理(远程和本地)
new_for_integration_test SomeIp代理(远程和本地)
Diagnostics代理(远程和本地)
VsidlSchemas代理(远程和本地)

表格的数据源是指图 1 中的调用。