Orchestrator 是一个本地 SDV 代理,在每个虚拟机 (VM) 上运行,并提供一种机制来控制何时应创建、启动、停止或销毁服务包。这是通过编排配置完成的,您可以在其中定义一组规则,用于确定何时以及如何对服务包实例执行操作。这些规则基于车辆、电源和自定义模式。
您可以在配置 APEX 中或通过每个虚拟机的配置来配置 Orchestrator。通过此分布式配置系统,每个服务包的各个部分都可以通过服务包注册表独立更新,如图所示。
图 1. 编排器配置图。
与车辆无关的配置不会因 OEM 或车辆而异。每个 OEM 的所有车辆上的配置都保持不变。不同 OEM 的不同车辆上的车辆专属配置可能会有所不同,但特定 OEM 制造的所有车辆的配置可能相同。
配置 APEX
在运行时,Orchestrator 会前往服务包注册表,为每个服务包提取 SDV 编排,并加载和解析每个配置。如需了解详情,请参阅编排元数据。
每个虚拟机配置
Orchestrator 启动时,会加载并解析虚拟机配置(如果存在)。此配置文件的绝对路径通过系统属性 persist.sdv.orchestrator_config_path 和 ro.boot.sdv.orchestrator_config_path 指定。
系统会在启动时根据以下层次结构确定虚拟机配置文件路径:
系统会检查
persist.sdv.orchestrator_config_path属性。如果它有值,则使用该路径。此值会在重新启动后保留,或在运行时设置。如果
persist.sdv.orchestrator_config_path为空,系统会检查ro.boot.sdv.orchestrator_config_path属性。如果ro.boot.sdv属性有值,该路径会被复制到 persist 属性,并用于当前启动和所有未来启动(除非被覆盖)。
persist.sdv.orchestrator_config_path
persist.sdv.orchestrator_config_path 是 SDV Orchestrator 代理用于获取其配置文件路径的主要属性。这是一个永久性属性,这意味着其值会在设备重新启动后保存。您可以在运行时更改该值,这对于测试或特定场景(例如端到端测试)非常有用。
您可以在运行时使用 setprop 命令设置该值,也可以在构建时使用 Makefile(扩展名为 .mk)或资源脚本文件(扩展名为 .rc)设置该值。
在运行时设置属性
在运行时设置属性对于测试或进行临时更改非常有用,因为该值会在重新启动后保存:
adb root
adb shell setprop persist.sdv.orchestrator_config_path {$path_to_file}.textproto
在构建时设置属性
如需将此属性设置为设备 build 配置的一部分,请在产品或开发板的 makefile 中添加一行代码。这非常适合为新设备映像设置默认值。
# Add this line to a product's or device's .mk file
PRODUCT_PROPERTY_OVERRIDES += persist.sdv.orchestrator_config_path={$path_to_file}.textproto
您也可以在资源脚本文件中设置此属性:
# Add this line to an .rc file
on {$property}
setprop persist.sdv.orchestrator_config_path {$path_to_file}.textproto
ro.boot.sdv.orchestrator_config_path
ro.boot.sdv.orchestrator_config_path 是一个启动时只读属性,用于为 persist.sdv.orchestrator_config_path 属性提供初始值。如果系统启动时 persist.sdv.orchestrator_config_path 为空,则 ro.boot.sdv.orchestrator_config_path 的值会复制到其中。设置 persist.sdv.orchestrator_config_path 后,此属性不会在后续启动时覆盖它。
您可以使用 bootconfig 或内核 cmdline 设置 ro.boot.sdv.orchestrator_config_path。
文件格式
以 .textproto 格式(例如结构化文本)定义编排配置,以便在运行时加载新配置。
配置语法
本部分介绍了配置语法。
服务套餐
每个服务包都必须使用服务包配置进行定义,该配置用于在 Orchestrator 中标识服务包,并用于处理服务包实例的生命周期。服务包配置定义了以下内容:
借助
InstanceToGroupMapping,您可以在组中添加服务包的实例,以在同一服务包的实例之间建立依赖关系。InstancesStates定义服务包实例的不同状态。InstancesStateConfiguration定义了如果条件的计算结果为true,则必须将服务包实例设置为的状态(来自InstancesStates)。ServiceBundleConfig包含有关特定服务包及其实例的信息。它包含相应 bundle 的InstanceToGroupMapping和InstancesStateConfiguration。CustomModes定义了允许该软件包发布的自定义模式列表。CustomModes用于防止未经授权的软件包修改自定义模式的值。此字段是可选字段,因为服务包可能不会发布到任何自定义模式。如需了解详情,请参阅自定义模式。
必需的 bundle 配置
捆绑包配置至少提供以下属性:
service_bundle_config {
package_name: "package_name"
service_bundle_name: "service_bundle_name"
instance: "instance_1"
instance: "instance_n"
}
此声明定义了 n 个服务包实例,每个实例都有各自的 FQIN:
vm_name.package_name.service_bundle_name.instance_1
…
vm_name.package_name.service_bundle_name.instance_n
配置中未明确声明虚拟机名称。由于配置是按虚拟机定义的,因此虚拟机名称始终是部署配置文件的虚拟机的名称,并且编排代理已经知道该名称。
配置实例
声明服务包实例没有任何效果。如需由 Orchestrator 执行,必须配置实例。例如,必须告知 Orchestrator 实例应在哪些条件(或虚拟机或车辆的状态)下运行。如需配置实例,应通过以下方式定义配置状态:
condition是应评估的虚拟机或车辆状态的表达式。instances_states是每个实例的一组状态,如果条件的计算结果为true,则应应用这些状态。
如需了解详情,请参阅条件。
service_bundle_config {
package_name: "oem.package"
service_bundle_name: "OemApplication"
instance: "adaptive_light"
instance: "reserve_light"
state {
condition {
power_state: "ON"
}
instances_states {
started: "adaptive_light"
created: "reserve_light"
}
}
}
实例到组的映射
您还可以通过将服务实例添加到服务组中来配置服务实例。在服务包配置级别,您可以将实例添加到群组。然后,您可以在虚拟机配置级别配置组。如需了解详情,请参阅下一部分和服务包。
service_bundle_config {
package_name: "oem.package"
service_bundle_name: "OemApplication"
instance: "fog_front_light"
instance: "fog_rear_light"
instance: "turn_signal_light"
instance: "light_flasher_display"
# Declare that fog_light contains fog_front_light and fog_rear_light.
group_mapping {
group: "fog_light"
instance: "fog_front_light"
instance: "fog_rear_light"
}
# Declare that flasher_light contains turn_signal_light and light_flasher_display.
group_mapping {
group: "flasher_light"
instance: "turn_signal_light"
instance: "light_flasher_display"
}
}
Proto 架构
以下是 proto 架构示例:
// Service bundle configuration.
//
// Defines service bundle data, its instances and configuration for instances
// states depending on the state of the system
message ServiceBundleConfig {
// Required. Name of the service bundle.
string service_bundle_name = 1;
// Required. Package name of the service bundle.
string package_name = 2;
// Required. Service instances.
repeated string instance = 3;
// Configuration for instances states depending on the state of the system.
repeated InstancesStateConfiguration state = 4;
// Mapping of groups to their member service instances.
repeated InstanceToGroupMapping group_mapping = 5;
// Custom modes that this service bundle is allowed to set.
repeated string custom_mode = 6;
// Defines the retry policies for specific instances.
// If multiple mappings target the same instance, the one with the highest `max_retries`
// value takes precedence. This applies across all configuration files.
repeated InstanceToRetryMapping retry_mapping = 7;
}
// Mapping of instances to their retry configuration.
message InstanceToRetryMapping {
// Required.
//
// Name of the instances for which the given retry configuration is applied.
repeated string instance = 1;
// Required.
//
// The configuration that defines the restart and retry strategy for the instances.
RetryConfiguration retry_config = 2;
// Configuration for retry and restart.
// This configuration is applied after a failure on a transition or after the bundle instance
// has crashed. Upon a successful operation, the retry counter are reset to max_retries. This
// configuration can be applied to any service bundle, not only the monitored ones. If the
// configuration is not provided or none of the optional fields are filled, the default behavior
// stated is applied (the value from `ro.boot.sdv.orchestrator.recovery.max_retries`
// or zero if not set).
message RetryConfiguration {
// The number of times a retry/restart operation can be performed.
// Defines the number of times the Orchestrator retries a transition
// after a transient failure or after a bundle crash notification.
// This applies to creating, starting and destroying operations.
// The retry count resets to max_retries after a successful operation.
// If not set, the default configured value in the
// `ro.boot.sdv.orchestrator.recovery.max_retries` is used, or-if not set-
// it fallbacks to zero.
optional uint32 max_retries = 1;
}
}
// Mapping of groups to their member service instances.
message InstanceToGroupMapping {
// Required. Names of groups to which members are added.
//
// Group behavior is defined in VM configuration.
repeated string group = 1;
// Required. Names of instances to be included in the groups.
//
// Can reference only instance defined in the same config file.
repeated string instance = 2;
}
// Describes the state the service instances should be in after the state is executed.
//
// If there is no valid configuration for the instance in the specific system state, such instance is transitioned to the "destroyed" state.
//
// For the GroupsStates definition to be useful, at least one item should be present in any of the fields.
message InstancesStates {
// Names of the instances that must be in a "created" state.
repeated string created = 1;
// Names of the instances that must be in a "started" state, overrides "created" state.
repeated string started = 2;
// Names of the instances that must not run, overrides all other states.
repeated string destroyed = 3;
}
// Configuration for instances states depending on the state of the system.
message InstancesStateConfiguration {
// Condition for the system state under which the related instances states should be executed by Orchestrator.
//
// If omitted, the related instances states are always executed.
Condition condition = 1;
// Required. States of service bundle instances to be executed by Orchestrator if the condition is true.
InstancesStates instances_states = 2;
}
虚拟机级配置
虚拟机配置支持定义群组映射和群组配置。它用于在虚拟机级别对服务包之间的依赖关系进行建模,从而可以灵活地同时修改多个服务包的状态。组的所有实例都会进入指定状态。
Orchestrator 不保证状态更改的执行顺序。Orchestrator 会将每个实例提升到给定状态。
通过在任何配置部分中使用 group 名称,可以隐式声明组。例如,实例到组的映射、组到组的映射以及组配置状态。
群组到群组映射
群组可以包含其他群组。通过声明 group_1 包含 subgroup_2,我们实际上将 subgroup_2 中的所有服务实例都添加到了 group_1。
例如:
# Declare that body contains fog_light and flasher_light.
group_mapping {
group: "body"
subgroup: "fog_light"
subgroup: "flasher_light"
}
配置群组
声明群组没有任何效果。如需由 Orchestrator 执行,必须配置群组。例如,必须告知 Orchestrator 应在哪些条件或虚拟机或车辆状态下运行这些组。
您可以通过与服务实例类似的方式(即使用配置状态)来配置群组。唯一的区别是在语法中使用 groups_states 而不是 instances_states:
state {
condition {
power_state: "ON"
}
groups_states {
started: "Body"
started: "Adas"
}
}
Proto 架构
以下是一个 proto 架构示例:
// VM configuration.
//
// Defines group-to-group mappings and configuration for groups
// states depending on the state of the system.
//
// Configurations of service bundles can also be defined in VM configuration (as well as in a separate configuration file).
message VmConfig {
// Group to member groups mapping.
repeated GroupToGroupMapping group_mapping = 1;
// Configuration of group states.
repeated GroupsStateConfiguration state = 2;
// Required. We also allow to configure individual service bundles in the VM config, to simplify development and migration from the monolithic configuration.
repeated ServiceBundleConfig service_bundle_config = 3;
}
// Mapping of groups to their member groups.
message GroupToGroupMapping {
// Required. Names of groups to which members are added.
repeated string group = 1;
// Required. Names of member groups to be included in the groups.
repeated string subgroup = 2;
}
// Describes the state the service instance groups should be in after the state is executed.
//
// If group configuration is valid in a specific system state, the configured state is applied to
// all group members. After that, the normal service instance configuration rules still apply:
// - "destroyed" > "started" > "created" precedence
// - not configured means the instance should be moved to the default state
//
// For the GroupsStates definition to be useful, at least one item should be present in any of the fields.
message GroupsStates {
// Names of the groups that must be in a "created" state.
repeated string created = 1;
// Names of the groups that must be in a "started" state, overrides "created" state.
repeated string started = 2;
// Names of the groups that must not run, overrides all other states.
repeated string destroyed = 3;
}
// Configuration for group states depending on the state of the system.
message GroupsStateConfiguration {
// Condition for the system state under which the related group states should be executed by Orchestrator.
//
// If omitted, the related groups states are always executed.
Condition condition = 1;
// Required. States of service bundle groups to be executed by Orchestrator if the condition is true.
GroupsStates groups_states = 2;
}
配置状态
配置状态(状态)定义服务实例或组何时启动、停止或销毁,由 conditions 和 instances_states(软件包配置)以及 groups_states(虚拟机配置)组成。
条件
条件允许模型使用布尔条件,当该条件的求值结果为 true 时,系统会应用定义的实例状态。条件具有以下特征:
基于支持的信号(例如电源、车辆和自定义模式)的任意复杂布尔表达式(由
and或not表达式构成)。(可选)没有条件的配置状态始终处于活跃状态,这意味着其求值结果为
true
实例状态和群组状态
instances_states 和 groups_states 具有以下特征。
指定编排代理需要哪些状态才能应用于给定实例或组,前提是状态为
active将状态应用于群组时,该状态会应用于群组中的每个服务包实例。实例进入该状态时,不应用任何顺序。
支持的州包括:
调用
Service::on_start后,started。created在调用
Service::new之后但在调用Service::on_start之前。或
在调用
Service::on_stop之后但在调用Service::drop之前。
调用
Service::drop后,destroyed。
规则集
配置状态可以是有效或无效,具体取决于条件。多个状态可以同时处于活跃状态。当编排代理收到信号更新时,系统会先评估所有配置状态,然后再修改服务包的生命周期。服务实例状态根据以下规则进行评估:
当服务实例不处于任何活动状态时,它会被销毁。
当一个或多个活跃状态适用时,系统会按以下优先顺序应用:
destroyed具有绝对优先权。started的优先级高于created。
Proto 架构
以下是一个 proto 架构示例:
// A root boolean condition.
message Condition {
// Required.
oneof root {
// VPM power state condition.
string power_state = 1;
// VPM vehicle state condition.
string vehicle_state = 2;
// Custom mode state condition.
CustomState custom_state = 3;
// Negation of a nested condition.
Condition not = 4;
// Logical 'and' between conditions grouped in expression.
Expression and = 5;
// Logical 'or' between conditions grouped in expression.
Expression or = 6;
}
}
// Representation of Custom state condition.
//
// Custom mode(s) are defined by the OEM and are not standardized by the platform, in contrast with
// VPM modes (i.e. power and vehicle mode).
message CustomState {
// Custom mode being checked.
string mode = 1;
// State of the custom mode.
string state = 2;
}
// A set of conditions united under an 'and' or 'or' expression.
//
// Evaluation type ('and' or 'or') depends on the field in [Condition]/[Expression], where the
// expression is being used.
//
// At least one value in at least one of the fields is required.
message Expression {
// VPM power state condition.
repeated string power_state = 1;
// VPM vehicle state condition.
repeated string vehicle_state = 2;
// Custom mode state condition.
repeated CustomState custom_state = 3;
// Negation of a nested condition.
repeated Condition not = 4;
// Logical 'and' between conditions grouped in expression.
repeated Expression and = 5;
// Logical 'or' between conditions grouped in expression.
repeated Expression or = 6;
}
崩溃恢复和重启策略
Orchestrator 提供了一种强大的机制来处理服务包崩溃和生命周期转换失败。由于 Orchestrator 能够全面了解服务状态并管理模式转换,因此它是执行重启和重试策略的最合适组件。生命周期管理器 (LM) 通过 binder 终止通知向 Orchestrator 报告服务包崩溃。为避免对 LM 进行不必要的 binder 调用,Orchestrator 会缓存每个 bundle 的最后状态(无论是否成功),并且如果最后已知状态与新请求的状态相同,则不会重新应用转换。
重试配置
您可以使用 retry_mapping 在 Orchestrator 配置中为每个实例定义重启和重试策略。如果未在配置中设置 max_retries,则默认值取自 ro.boot.sdv.orchestrator.recovery.max_retries 系统属性。如果未设置此属性,则值会回退到 0。
max_retries:定义 Orchestrator 在发生暂时性故障或收到软件包崩溃通知后重试转换的次数。在操作成功或处理新模式后,重试计数器会重置为max_retries的值。如果多个映射定位到同一实例,则max_retries最高的映射优先。
配置示例
service_bundle_config {
package_name: "oem.package"
service_bundle_name: "OemApplication"
instance: "fog_front_light"
instance: "fog_rear_light"
# Defines the restart configuration mapping for specific instances.
retry_mapping {
instance: "fog_front_light"
instance: "fog_rear_light"
retry_config {
max_retries: 3
}
}
}
恢复行为
Orchestrator 的重启和重试逻辑可妥善管理多种故障场景:
- 正常运行期间崩溃:如果服务 bundle 在运行期间崩溃,Orchestrator 会应用重启策略,并尝试根据剩余重试次数将 bundle 恢复到上次请求的状态。
- 在模式转换期间崩溃:如果某个软件包在强制执行新模式时崩溃,重启请求会排入队列,稍后处理。请求处理完毕后,Orchestrator 会检查实例的最后一个状态,并且仅在实例未处于最后请求的状态(来自上一次模式转换)时才应用重启。
- 恢复期间的新模式:如果 Orchestrator 在重启软件包(或软件包位于要重启的实例队列中)时收到切换到新模式的请求,它会取消正在进行的恢复。新的模式转换会接管,并且重试计数器会重置,以便针对新的目标状态进行一组新的尝试。
Orchestrator 会区分 Lifecycle Manager 返回的不同错误类型,以确定重试策略:
- 暂时性错误(
SERVICE_NOT_FOUND、OPERATION_FAILED、INTERNAL_ERROR):Orchestrator 会重试操作,而不会执行任何特殊清理操作。 - 持续性错误(
VALUE_CORRUPTED、INVALID_ARGUMENT):Orchestrator 会假定服务软件包可能处于损坏状态,并尝试终止服务实例,然后再重试操作,以确保干净重启。 - 永久性错误 (
PERMISSION_DENIED):系统不会重试该操作,并且该 bundle 会被视为处于不可恢复的状态。
如果生命周期管理器崩溃,所有服务包进程都会丢失。由于实际状态未知,Orchestrator 会使每个实例失效,并应用具有剩余重试次数的重启策略,以使每个实例达到上次请求的状态。
为防止反复崩溃或失败的软件包出现无限恢复循环,只有在生命周期操作成功或请求新的模式转换后,重试计数器才会重置为 max_retries。如果某个 bundle 因连续失败(例如,转换失败后发生崩溃)而用尽重试次数,则在重试计数器重置之前,该 bundle 不会重启。
向健康监测器报告状态
Orchestrator 会公开一个内部 Binder 接口,Health Monitor (HM) 会注册到该接口,以便持续接收有关所有服务包状态的更新。通过此接口,Orchestrator 会主动报告以下两项内容:
- 生命周期状态:根据当前配置和活动模式(例如已启动、已创建或已销毁)确定的实例预期状态。
- 恢复状态:达到预期生命周期状态的状态,指示实例是否正常运行、当前是否在失败后重试,或者在用尽所有重试次数后是否未能恢复。
系统会报告所有实例(包括未注册为心跳监控的实例)的这些信息。HM 会使用这些信息来实现其 API,以报告虚拟机的状态。如需了解详情,请参阅健康状况监控。
示例
本部分提供了配置带条件的状态的示例。
基础服务示例
- 没有条件,因此始终处于有效状态。
- 启动单个服务实例。
state {
# Note: This state has no condition, hence its actions are valid throughout the lifetime of the program
instances_states { started: "ServiceBundleName" }
}
HVAC 应用示例
条件:在
custom_state != occupancy.OCCUPANCY_EMPTY || custom_state == preheat.PREHEAT_ON时处于有效状态。将多个与 HVAC 相关的服务实例声明为
started。
state {
condition {
or {
# I.e. when the vehicle is occupied (for example, by _DRIVER / _NON_DRIVER / _PET)
not {
custom_state {
mode: "occupancy"
state: "OCCUPANCY_EMPTY"
}
}
custom_state {
mode: "preheat"
state: "PREHEAT_ON"
}
}
}
# HVAC-related services
instances_states {
started: "HvacTemperatureCommand"
started: "TempSensorDriverZone"
started: "TempSensorPassengerZone"
started: "RefrigerantLoop"
}
}
节能示例
条件:在
custom_state == system_power.SYSTEM_POWER_LOW && custom_state == range_ext.RANGE_EXT_ON时处于有效状态。此状态可视为节能状态。
将一个与 HVAC 相关的服务实例声明为
destroyed。在此示例中,当
SYSTEM_POWER_LOW和RANGE_EXT_ON模式处于活跃状态时,HVAC 应用在没有RefrigerantLoop服务实例的情况下运行:state { condition { and { custom_state { mode: "system_power" state: "SYSTEM_POWER_LOW" } custom_state { mode: "range_ext" state: "RANGE_EXT_ON" } } } # Disable services with high power consumption instances_states { destroyed: "RefrigerantLoop" } }
船上生活示例
条件:如果
power_state == ON && vehicle_state == LIFE_ON_BOARD,则处于活跃状态。此状态可以视为有人在车内且汽车已启动。
将温度传感器声明为正在运行。
当车内有人时,系统会出于安全原因监控温度等项目。
state {
condition {
and {
power_state: "ON"
vehicle_state: "LIFE_ON_BOARD"
}
}
# Temperature monitoring services
instances_states {
started: "TempSensorDriverZone"
started: "TempSensorPassengerZone"
}
}
示例
本部分提供了完整示例,其中包含:
服务包级 proto 配置,引入了包含两个实例的服务包,每个实例都是一个组的一部分
虚拟机级 proto 配置,引入了根据模式与组进行交互的逻辑
服务包级配置
# proto-file: //system/software_defined_vehicle/orchestration/distributed_config/src/protos/service_bundle_config.proto
# proto-message: ServiceBundleConfig
package_name: "oem.package"
service_bundle_name: "OemApplication"
instance: "fog_front_light"
instance: "fog_rear_light"
instance: "turn_signal_light"
custom_mode: "FOG"
custom_mode: "TURN"
group_mapping {
group: "fog_light"
instance: "fog_front_light"
instance: "fog_rear_light"
}
group_mapping {
group: "flasher_light"
instance: "turn_signal_light"
}
state {
condition {
power_state: "ON"
}
instances_states {
created: "turn_signal_light"
destroyed: "fog_front_light"
destroyed: "fog_rear_light"
}
}
虚拟机级配置
# proto-file: //system/software_defined_vehicle/orchestration/distributed_config/src/protos/vm_config.proto
# proto-message: VmConfig
group_mapping {
group: "lights"
subgroup: "fog_light"
subgroup: "flasher_light"
}
state {
condition {
custom_state {
mode: "FOG"
state: "ON"
}
}
groups_states {
started: "fog_light"
}
}
state {
condition {
custom_state {
mode: "TURN"
state: "RIGHT"
}
}
groups_states {
started: "flasher_light"
}
}
state {
condition {
vehicle_state: "SUSPEND_TO_RAM_ENTER"
}
groups_states {
created: "lights"
}
}
配置捆绑包管理并行处理
ro.boot.sdv.max_bundles_management_threads 系统属性是一个关键的调优参数,用于在服务包生命周期操作期间控制性能和资源消耗。它定义了服务包事务的最大并行度,并直接影响两个核心服务:
Orchestration Engine:此服务会读取该属性,以确定 Orchestrator 可以对 Lifecycle Manager 进行多少次并发调用(例如
startService、stopService)。这对于启动和模式转换期间的性能至关重要,因为在这些期间,许多 bundle 可能会同时更改状态。Lifecycle Manager:此服务使用该属性的值来计算其 Binder 线程池的大小,该线程池负责处理所有传入请求。这可确保 LM 有足够的线程来处理来自 Orchestrator 的并发请求。
如果未设置此属性,则两项服务的默认值均为 12。
配置方法
您可以在设备的 BoardConfig.mk 文件中设置该属性,方法是将其添加到 BOARD_BOOTCONFIG 变量中。这可确保每次设备启动时都会应用该值。
BOARD_BOOTCONFIG += \
androidboot.sdv.max_bundles_management_threads=8
如需更改设备的值,请在相应的 BoardConfig.mk 文件中修改此行,然后重新构建。
启动时间优化
ro.sdv.orchestrator.state.ready 是一个 write-once 布尔值属性,属于启动时性能优化策略的一部分。这表示 Orchestration 代理已完成初始化,并已准备好开始管理服务包的生命周期。其主要目的是通过控制其他 SDV 代理的启动顺序,优先启动 Orchestrator 及其托管式服务包。
- 设置者:编排代理。
- 时间:在启动序列期间执行一次。
- 用法:此属性由 init 系统使用,用于控制大多数 SDV 代理(更新管理器、VSIDL 提供程序、健康状况监控器、服务发现、数据隧道、RPC、VPM 和遥测)的启动顺序。通过尽早启动 Orchestrator 并让其他代理等待此属性,系统可确保 Orchestrator 能够开始启动服务包的关键任务,而不会争用系统资源。
性能
在系统启动期间,同时启动所有代理可能会导致资源争用,从而减慢整个启动过程。为了缓解这种情况,系统会使用系统属性强制执行依序启动:
- 服务包注册表:首先启动,以加载所有服务包元数据。
- Lifecycle Manager 和 Orchestrator:这些核心代理会在注册表准备就绪后立即启动。这种提前启动至关重要,因为它使 Orchestrator 能够开始评估其配置,并准备立即启动服务包。
- 其他 SDV 代理:仅在 Orchestrator 准备就绪后启动。
这种受控序列可确保 Orchestrator 优先使用系统资源,以便尽早启动服务包,从而实现更快、更确定且更高效的系统启动。
Orchestrator 消耗的模式
编排代理会持续订阅 VPM 传输的车辆和电源模式。在 Orchestrator 与车辆和电源管理 (VPM) 系统之间建立初始连接后,Orchestrator 会将以下布尔值系统属性设置为 true:
sdv.orchestrator.bootup.power_mode.readysdv.orchestrator.bootup.vehicle_mode.ready
编排代理以配置文件为参考,根据收到的模式的当前值,动态计算应处于运行状态的服务包集。然后,Orchestrator 会与生命周期管理器通信,发出不同的命令,使服务包的实际状态与计算出的目标状态保持一致。
车辆和电源状态
借助车辆模式和电源管理 (VPM) 代理,SDV 组件可以了解车辆的当前状态,例如运行模式(例如,处于“停车”或“驾驶”状态)和电源状态(例如,“开启”和“暂停”)。 Orchestrator 会评估这些值,以根据 Orchestrator 配置确定应运行哪些服务包。如需了解详情,请参阅车辆和电源管理。
自定义模式
由于车辆模式数量众多,我们无法对所有车辆模式进行建模。每个 OEM 都有不同的需求,标准化车辆模式无法满足所有 OEM 用例。因此,我们支持 OEM 专用模式,称为自定义模式。这些模式不会扩展现有的车辆和电源模式。而是提供了一种定义新模式的方法。
功能:
全局范围:自定义模式是全局性的,统一应用于 Orchestrator 管理的所有虚拟机。
组成:每项自定义模式更改都包含两个元素:
名称:由 OEM 选择的用于表示自定义模式的唯一标识符。
值:自定义模式的当前状态,如果未设置任何值,则可以为
UNDEFINED。
Orchestrator 角色:Orchestrator 充当自定义模式值的被动接收器。
服务包角色:每个服务包可以拥有多个自定义模式,并且可以向任何模式发布新值。多个服务包可以拥有相同的自定义模式,这意味着自定义模式可以从不同的来源接收新值。
验证责任:OEM 负责确保状态转换有效。Orchestrator 接受任何新值。
预估特征:
预估数量:电源和车辆模式管理大多数服务包的生命周期,自定义模式则起到补充作用。我们预计自定义模式的数量级为数十个,而不是数百个。
预计用时:模式不会定期发送。相反,模式是事件驱动的,由特定操作触发,例如开门、启动停车序列、启动充电周期以及其他具有 OEM 定义的重要性的类似事件。
自定义模式设计可让您灵活地定义和管理特定模式,同时让 Orchestrator 保持与底层状态机逻辑无关。
支持的模式
为确保服务包仅发布到其拥有的自定义模式,每个服务包都必须在其 Orchestrator 配置中明确声明拥有的自定义模式列表,该配置可在具有服务包注册表的本地虚拟机中使用。尝试发布到未声明的自定义模式的操作会被舍弃。
为了声明允许服务包发布(从而拥有)的自定义模式,service_bundle_config proto 架构扩展了以下内容:
// Service bundle configuration.
//
// Defines service bundle metadata, its instances, and configuration for instances
// lifecycle states depending on the state of the vehicle.
message ServiceBundleConfig {
[...]
// The list of custom modes that this service bundle publishes.
repeated string custom_mode = 5;
}
根据模式配置 bundle
现有的 Orchestrator proto 配置(Condition 组件)支持基于自定义模式对服务包进行操作:
message Condition {
oneof root {
string power_state = 1;
string vehicle_state = 2;
CustomState custom_state = 3;
Condition not = 4;
Expression and = 5;
Expression or = 6;
}
}
message CustomState {
// Custom mode being checked.
string mode = 1;
// State of the custom mode.
string state = 2;
}
Proto 示例
以下示例展示了如何配置服务包的实例,以便根据 TURN 和 FOG 状态启动:
service_bundle_config {
package_name: "oem.package"
service_bundle_name: "OemApplication"
instance: "flasher_light"
// Service bundle is allowed to set values for the TURN mode
custom_mode: "TURN"
// Service bundle is allowed to set values for the FOG mode
custom_mode: "FOG"
state {
condition {
custom_state {
mode: "TURN"
state: "LEFT"
}
}
instances_states {
started: "flasher_light"
}
}
state {
condition {
custom_state {
mode: "FOG"
state: "ON"
}
}
// Group assumed to be defined containing all FOG lights instances.
groups_states {
started: "fog_lights"
}
}
}
设置新的自定义模式
设置新自定义模式值的过程从服务包开始,服务包会将所需值传达给在同一虚拟机上运行的本地 Orchestrator。然后,Orchestrator 会验证服务包是否具有发布到指定自定义模式所需的权限,并参考 .textproto 中定义的配置,以确定是否应将该值传播到其他虚拟机。传播完成后,每个 Orchestrator 都会查看其配置,以找到应更改状态的服务包列表。
RPC
在每个虚拟机上运行的每个 Orchestrator 都会创建一个 RPC 服务器,用于监听新的自定义模式值。每个想要更新自定义模式的服务包都必须创建到服务器的 RPC 客户端。系统会强制执行 ACL,以防止未经授权的软件包连接到服务器。
通过 RPC 设置新值的 proto 定义如以下示例所示:
syntax = "proto3";
import "google/protobuf/timestamp.proto";
package com.sdv.google.Orchestrator;
// Representation of the request used by service bundles to update a custom mode.
// Service bundles are permitted to update only the custom modes specifically designated
// for them within the Orchestrator configuration.
message SetCustomStateRequest {
// Required.
// The name of the custom mode.
// The mode string can not be longer than 56 characters and can only contain
// letters, numbers, dashes, dots and underscores: [a-zA-Z0-9_-.].
// No other special character nor spaces should be present in the mode.
string mode = 1;
// Required.
// The new value for the custom mode.
// The value string can not be longer than 56 characters and can only contain
// letters, numbers, dashes, dots and underscores: [a-zA-Z0-9_-.].
// No other special character nor spaces should be present in the value.
string value = 2;
// Required.
// The timestamp in which the new custom mode value was set. This is used to
// prevent race conditions whenever different service bundles in different
// VMs want to set a new value for the same custom mode.
// We use this timestamp to order the requests and we promise eventual
// consistency: while temporary inconsistencies may occur, the system will
// eventually converges to the correct state.
.google.protobuf.Timestamp timestamp = 3;
}
// Representation of the set custom state response.
message SetCustomStateResponse {}
// Orchestrator interface for service bundles that update the value of a
// custom mode.
// When a new value is received, it is propagated to Orchestrators running on
// other VMs.
service CustomStateService {
// Updates the value for the custom mode.
// Returns the error:
// - PermissionDenied: the service is not authorized to update the custom mode.
// - InvalidArgument: the provided mode and/or value are not valid.
rpc SetCustomState(SetCustomStateRequest) returns (SetCustomStateResponse) {};
}
取消电源转换
Orchestrator 允许通过 SHUTDOWN_CANCELLED 电源模式(由 VPM 发送到 Orchestrator)取消正在进行的电源转换。
以下面的 Orchestrator 配置为例:
state {
condition {
power_state: "SUSPEND_TO_RAM_ENTER"
}
instances_states {
started: "instance-1"
started: "instance-2"
started: "instance-3"
}
}
收到 SHUTDOWN_CANCELLED 模式后,Orchestrator 的行为由两种主要场景决定。在这两种情况下,SHUTDOWN_CANCELLED 电源模式都会附加到队列末尾。然后,在队列中的元素被使用后执行 SHUTDOWN_CANCELLED。
场景 1:当前正在进行的模式是电源模式
如果 Orchestrator 正在执行电源模式更新,则会请求取消正在进行的模式。虽然 Lifecycle Manager 本身不支持取消正在进行的转换,但 Orchestrator 会验证是否没有发起新的服务包请求。
示例:如果上一个示例的配置中的 instance-1 在收到 SHUTDOWN_CANCELLED 模式时正在启动,则 instance-1 会完成启动。不过,instance-2 和 instance-3 不会继续转换到已启动状态。
场景 2:处理队列中存在电源模式
如果 Orchestrator 正在处理非电源模式更新,并且要执行的模式队列中存在电源请求,则电源转换会从队列中移除。这会阻止其执行。
示例:使用上一个示例中的配置,如果 Orchestrator 正在处理与电源无关的更新(例如车辆更新),并且 SUSPEND_TO_RAM_ENTER 位于队列中,则收到 SHUTDOWN_CANCELLED 会导致所有实例(instance-1、instance-2、instance-3)都无法启动。
实现示例
如果客户端想要使用中间件生成的代码来创建 RPC 服务器的客户端,其目录可能如下例所示:
# proto-file: //system/software_defined_vehicle/vsidl/language/src/protos/sdv/vsidl/v1/syntax.proto
# proto-message: VsidlEntry
package: "package_name"
service_bundle {
name: "service_bundle_name"
client {
service: "com.android.sdv.orchestrator.CustomStateService"
}
}
生成代码时,您必须将依赖项添加到 Orchestrator 目录中:
--dependency-catalog-path orchestration/engine/stable/vsidl/*
用于发送新值的客户端代码如下所示:
let fqin = ServiceFqin::builder()
.sdv_vm_name("vm_name")
.sdv_package_name("package_name")
.service_bundle_name("service_bundle_name")
.service_instance_name("instance_name")
.build()
.unwrap();
let context_ref = ContextRef::create(fqin);
let comms = Arc::new(SdvComms { context: context_ref });
// service_bundle_name is the bundle generated with middleware code that defines
// the RPC client to "com.android.sdv.orchestrator.CustomStateService".
let client = service_bundle_name::new(comms).await.unwrap();
let rpc_client = client
.create_rpc_client::<Client>(
UnitName::builder()
.vm_name(comms.context.get_self_fqin().get_sdv_vm_name())
.package_name("com.android.sdv.orchestrator")
.bundle_name("OrchestratorServiceBundle")
.service_unit_name(Client::DEFAULT_UNIT_NAME)
.build()
.unwrap(),
ClientOptions::default(),
)
.await;
let client = Arc::new(rpc_client.unwrap());
let request = SetCustomStateRequest {
mode: custom_mode_name,
value: custom_mode_value,
timestamp: MessageField::some(Timestamp::now()),
..Default::default()
};
let result = client.SetCustomState(&request).await;
// Process result
调试工具
Orchestrator 代理支持 dumpsys 工具。您可以通过在正在运行的 SDV 实例上运行以下命令来调用它:
adb shell dumpsys com.google.sdv.ISdvAgent/orch
使用此工具可调试 Orchestrator 代理并深入了解其内部状态。这样做会显示:
- 当前模式状态:查看处于活动状态的车辆模式、电源模式和自定义模式。
- 自定义模式发布者:确定哪些服务可以发布自定义模式(以及发布到哪些模式)。
- 每项服务所需的状态:根据预定义条件和当前模式了解每个服务包的状态。这有助于诊断服务可能未处于预期状态的原因。
- 模式强制执行状态:清楚了解正在进行的强制模式,或者上次强制执行的模式(如果当前没有正在进行的强制模式)。
- 模式强制执行队列:查看等待强制执行的模式。
例如:
AGENT NAME: SDV Agent dump - Orchestrator
AGENT FQIN: instance1:com.android.sdv.orchestrator.OrchestratorServiceBundle/default
AGENT STATE: See orchestrator state below.
----------------
----------------
INTERNAL STATE REPORTERS:
*NAME: Configuration state
*REPORT:
Active modes:
MODE VALUE TIMESTAMP (scs, ns)
Power POWER_OFF_EXIT -
Vehicle VEHICLE_ON -
Custom("CHARGING") ON 1750757590 (scs) 466507459 (ns)
Custom("TIRE_PRESSURE") front-left 1750757570 (scs) 554522995 (ns)
Modes allowed to publish by bundle (FQIN: modes):
com.android.sdv.sample.orchestration/CustomModeControlBundle: CHARGING, TIRE_PRESSURE
Requested state for instances:
STATE FQIN
Started com.android.sdv.sample.orchestration/CustomModeControlBundle/always-started-instance
Started com.android.sdv.sample.orchestration/OrchestratedServiceBundle/my-instance
Started com.sdv.oem.sample.diagnostics/DiagnosticsSampleWithDataItem/instance
Started com.sdv.oem.sample.diagnostics/DiagnosticsSampleWithEvent/instance
Started com.sdv.oem.user_preferences/UserPreferencesServiceBundle/default
----------------
*NAME: Engine state
*REPORT:
Last mode enforced was Custom("CHARGING") with value "ON"
Next modes to process: []
----------------
如需详细了解由 Orchestrator 管理的各个服务包,请使用 Lifecycle Manager 中的现有 dumpsys,如下所示:
dumpsys google.sdv.lifecycle.ILifecycleManager/default
这样做可提供有关每个服务的生命周期状态的详细信息。将 Orchestrator dumpsys 输出与 Lifecycle Manager 的输出相结合,可以全面了解虚拟机中服务包的生命周期。