VSIDL Provider for reflection

The VSIDL Provider is a set of libraries and tools that allow service bundles to provide VSIDL-declared metadata to the SDV platform agents (Diagnostics, Telemetry, and SOME/IP).

In particular, VSIDL provider enables SDV Agents to discover the following metadata:

VSIDL Provider guide for service bundle developers

The VSIDL Provider library performs the following operations.

  • Locates files in two specific places:
    • Within Apexes in paths defined in sdv_service_bundle_metadata.
    • On the image in static paths.
  • Initiates RPC calls to query the API on agents residing on the same or different VMs.

Figure 1.VSIDL Provider Overview.

If you are developing a service bundle, you don't need to know the specifics of the VSIDL Provider library. You may just follow these steps, that enable the VSIDL Provider to find the files it needs at runtime.

Generate Runtime Configs for Catalog

All three types of files (vsidl schemas, diagnostics declarations, someip mappings) are generated from the vsidl_rc_generator tool.

Use the vsidl_rc_generator host binary tool with the same parameters as used for vsidlc and the following additional parameters:

  • --variant runtime-config-prebuilts
  • --filegroup to specify the filegroup target name that contains all files of the catalog (including the Android.bp).

For reference, the relevant vsidlc parameters are the following:

  • --catalog-path to specify root path of catalog.
  • --dependency-catalog-path to specify dependent catalogs.
  • -- -path to specify where to write the Android.bp with all the generated genrule and prebuilt_etc targets.

The generator will create an Android.bp file with relevant genrule and prebuilt_etc targets. On top of the generated target blocks in Android.bp, there will be comments, that indicate the intended usage of their respective targets.

Update APEX's Android.bp

As indicated by the comments of the generated Android.bp file, that read:

// Usage: add the following line to ... declaration

You should add these targets (below the indicated Usage comments) to the Android.bp that define the Apex:

apex {
    name: "some_apex_name",
    ...
    prebuilts: [
      // ADD THE prebuilt_etc TARGETS HERE
    ],
    ...

}

Update APEX's sdv_service_bundles_manifest.textproto

Within the sdv_service_bundle_metadata blocks of the Apex's sdv_service_bundles_manifest.textproto files, you need to define (only for applicable paths):

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

Don't define your own paths. Instead copy the paths shown in the generated Android.bp file's comments, found as:

// + vsidl_schemas_path:
// + diagnostics_config_path:
// + external_protocol_mapping_path:

Doing this enables the VSIDL Provider instance to query from the paths specified by in the respective sdv_service_bundle_metadata entries.

Add Targets to Image

The generated Android.bp files also generate targets that can be loaded on the image directly. The comments also indicate the targets that are supposed to be used in this way, by:

// Usage: add this target to the VM image.

The generated prebuilt_etc target will place files that are generated with the genrules at a pre-specified location on the image. You need to include the prebuilt_etc targets in the respective *.mk files (like, for example, device/google/sdv/sdv_core_base/sdv_samples_automotive_services.mk).

VSIDL Provider Guide for Platform Developers

Generally, if you are developing SDV Agent that needs reflection capabilities, you can use VSIDL provider library.

The VSIDL Provider library API contains the following functions:

    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>;

where

pub type AvailabilityStream = Pin<Box<dyn Stream<Item = AvailabilityChangeEvent> + Send>>;

All functions are queried using a source_fqin parameter. This ensures that different FQINs using the same unit_type or message_name return the correct data. The parameter directs the VSIDL provider library to the specific APEX containing the most accurate message schema. This is necessary because APEXes are updated independently and may use different schemas for the same protobuf message or service.

Usage of get_message_descriptor function

This is returning purely the pub struct MessageDescriptor from the external crate that is used for reflection. A MessageDescriptor is a piece of metadata that allows for reflection, enabling dynamic inspection and manipulation of protobuf messages at runtime.

Usage of get_publication_descriptor function

This function returns a PublicationDescriptor, which is:

pub struct PublicationDescriptor {
    /// Message descriptor for publication.
    pub message_descriptor: MessageDescriptor,

    /// Information about the size of the publication message.
    pub size_metadata: SizeMetadata,
}

The size_metadata field contains information about the size and constraints of a publication's message. This metadata is derived from the VSIDL configuration.

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>,
}

Usage of get_rpc_method_descriptor function

This function returns a RpcMethodDescriptor, which is:

pub struct RpcMethodDescriptor {
    /// Message descriptor for RPC request.
    pub request_message: Option<MessageDescriptor>,

    /// Message descriptor for RPC response.
    pub response_message: Option<MessageDescriptor>,
}

This struct holds the MessageDescriptor for both the request and response messages of the RPC method.

Usage of get_someip_mappings function

This is a function for retrieving local SOME/IP service mappings, which are defined in core_services/vsidl/protos/sdv/someip/v1/someip.proto.

Usage of get_diagnostics_declaration function

This is a function for retrieving diagnostics declarations, which are defined in core_services/vsidl/protos/sdv/diagnostics/v1/diagnostics_syntax.proto

Usage of subscribe_availability_change_by_vm function

This function returns an availability stream for a specified virtual machine, serving as a critical fallback mechanism. Use it when standard VSIDL Provider API calls fail with an SdvStatusCode::Unavailable error, allowing the system to efficiently wait for the VSIDL provider interface to come back online.

Key behaviors of this function include:

  • Immediate emission: Upon subscription, the stream emits the current availability status of the target virtual machine.
  • Behavioral parity: The resulting stream behaves identically to the subscribe_service_unit_change_by_name function used by the ServiceDiscoveryManager.

VSIDL Provider Agent

Every VM is running its own VSIDL Provider agent, which is essentially an RPC server forwarding requests on the VSIDL Provider API (of a local instance of the library within the agent). The agent is used to query the VSIDL Provider on a different VM, that is, a service on one VM can query VSIDL metadata from another VM using this agent.

Usage of the API in the codebase

SOMEIP:

  • get_publication_descriptor (all struct fields are used)
  • get_rpc_method_descriptor (all struct fields are used)
  • get_someip_mappings

Telemetry:

  • get_publication_descriptor (only the message_descriptor field is used)
  • get_rpc_method_descriptor (all struct fields are used)

Diagnostics:

  • get_message_descriptor
  • get_diagnostics_declaration

The various flavors with the various data sources and source priorities can be found in core_services/vsidl/provider/src/vsidl_provider.rs.

The vsidl_provider crate offers several public functions to create provider instances tailored for different SDV agents. Each configuration specifies a unique chain of data sources to resolve VSIDL-related data. The table outlines the behavior of each constructor function:

Constructor functionData typeData source lookup (and order)
new_for_vsidl_provider_agent SomeIpAPEXes
DiagnosticsAPEXes
VsidlSchemasAPEXes, files
new_for_diagnostics_agentDiagnosticsAgent (remote), APEXes
VsidlSchemasFiles
new_for_someip_broker_agent SomeIpAPEXes
VsidlSchemasFiles
new_for_telemetry_agentVsidlSchemasAgent (remote and local)
new_for_integration_test SomeIpAgent (remote and local)
DiagnosticsAgent (remote and local)
VsidlSchemasAgent (remote and local)

The table's data sources refer to calls in Figure 1.