L'orchestrateur est un agent SDV local qui s'exécute sur chaque machine virtuelle (VM) et fournit un mécanisme permettant de contrôler le moment où les groupes de services doivent être créés, démarrés, arrêtés ou détruits. Pour ce faire, vous devez utiliser une configuration d'orchestration dans laquelle vous définissez un ensemble de règles permettant de déterminer quand et comment les actions doivent être exécutées sur les instances de packs de services. Ces règles sont basées sur les modes véhicule, puissance et personnalisé.
Vous pouvez configurer Orchestrator dans les APEX de configuration ou via les configurations par VM. Ce système de configuration distribué permet de mettre à jour indépendamment des parties de chaque bundle de services via le registre des bundles de services, comme illustré ici.
Figure 1. Schéma de configuration de l'orchestrateur.
Les configurations indépendantes du véhicule ne changent pas en fonction de l'OEM ou du véhicule. La configuration reste la même sur tous les véhicules de chaque OEM. Les configurations spécifiques aux véhicules peuvent varier selon les véhicules et les OEM. Toutefois, la configuration peut être la même pour tous les véhicules fabriqués par un OEM spécifique.
Configuration des APEX
Lors de l'exécution, l'orchestrateur accède au registre du bundle de services pour récupérer une orchestration SDV pour chaque bundle de services, en chargeant et en analysant chaque configuration. Pour en savoir plus, consultez Métadonnées d'orchestration.
Configuration par VM
Lorsque l'orchestrateur démarre, il charge et analyse la configuration de la VM (le cas échéant). Le chemin d'accès absolu à ce fichier de configuration est spécifié par les propriétés système persist.sdv.orchestrator_config_path et ro.boot.sdv.orchestrator_config_path.
Le système détermine le chemin d'accès au fichier de configuration de la VM au démarrage en fonction de la hiérarchie suivante :
Le système vérifie la propriété
persist.sdv.orchestrator_config_path. Si elle a une valeur, ce chemin est utilisé. Cette valeur est conservée lors des redémarrages ou définie au moment de l'exécution.Si
persist.sdv.orchestrator_config_pathest vide, le système vérifie ensuite la propriétéro.boot.sdv.orchestrator_config_path. Si la propriétéro.boot.sdva une valeur, ce chemin est copié dans la propriété persist et utilisé pour le démarrage actuel et tous les démarrages futurs (sauf s'il est remplacé).
persist.sdv.orchestrator_config_path
persist.sdv.orchestrator_config_path est la propriété principale utilisée par l'agent SDV Orchestrator pour obtenir le chemin d'accès à son fichier de configuration. Il s'agit d'une propriété persistante, ce qui signifie que sa valeur est enregistrée lors des redémarrages de l'appareil. Vous pouvez modifier la valeur au moment de l'exécution, ce qui est utile pour les tests ou les scénarios spécifiques (par exemple, les tests de bout en bout).
Vous pouvez définir la valeur au moment de l'exécution à l'aide de la commande setprop, et au moment de la compilation à l'aide d'un fichier makefile (avec l'extension .mk) ou d'un fichier de script de ressources, avec l'extension .rc.
Définir la propriété au moment de l'exécution
Définir la propriété au moment de l'exécution est utile pour les tests ou pour apporter des modifications temporaires, car la valeur est enregistrée lors des redémarrages :
adb root
adb shell setprop persist.sdv.orchestrator_config_path {$path_to_file}.textproto
Définir la propriété au moment de la compilation
Pour définir cette propriété dans la configuration de compilation de votre appareil, ajoutez une ligne au fichier make de votre produit ou de votre carte. C'est idéal pour définir une valeur par défaut pour une nouvelle image d'appareil.
# Add this line to a product's or device's .mk file
PRODUCT_PROPERTY_OVERRIDES += persist.sdv.orchestrator_config_path={$path_to_file}.textproto
Vous pouvez également définir cette propriété dans un fichier de script de ressources :
# 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 est une propriété en lecture seule au démarrage utilisée pour fournir une valeur initiale à la propriété persist.sdv.orchestrator_config_path. Si persist.sdv.orchestrator_config_path est vide au démarrage du système, la valeur de ro.boot.sdv.orchestrator_config_path y est copiée. Une fois que persist.sdv.orchestrator_config_path a été défini, il ne sera pas écrasé par cette propriété lors des démarrages suivants.
Vous pouvez définir ro.boot.sdv.orchestrator_config_path à l'aide de bootconfig ou de la ligne de commande du noyau.
Format de fichier
Définissez la configuration de l'orchestration au format .textproto (par exemple, dans un texte structuré) afin que les nouvelles configurations puissent être chargées au moment de l'exécution.
Syntaxe de configuration
Cette section décrit la syntaxe de configuration.
Packs de services
Chaque bundle de services doit être défini avec la configuration du bundle de services, qui identifie le bundle dans l'orchestrateur et est utilisé pour gérer le cycle de vie de l'instance du bundle. La configuration du bundle de services définit les éléments suivants :
InstanceToGroupMappingvous permet d'inclure une instance du bundle de services dans un groupe pour établir des dépendances entre les instances du même bundle de services.InstancesStatesdéfinit les différents états de l'instance du bundle de services.InstancesStateConfigurationdéfinit l'état (à partir deInstancesStates) dans lequel une instance de pack de services doit être définie si la condition renvoie la valeurtrue.ServiceBundleConfigcontient des informations sur le bundle de services spécifique et ses instances. Il contient, pour le bundle, lesInstanceToGroupMappingetInstancesStateConfigurationrespectifs.CustomModesdéfinit une liste de modes personnalisés que le bundle est autorisé à publier.CustomModesest utilisé pour empêcher un bundle non autorisé de modifier la valeur d'un mode personnalisé. Ce champ est facultatif, car il est possible que le forfait de services ne soit publié dans aucun mode personnalisé. Pour en savoir plus, consultez Modes personnalisés.
Configuration requise du bundle
La configuration du bundle fournit au minimum les attributs suivants :
service_bundle_config {
package_name: "package_name"
service_bundle_name: "service_bundle_name"
instance: "instance_1"
instance: "instance_n"
}
Cette déclaration définit les instances de bundle de services n avec les FQIN respectifs :
vm_name.package_name.service_bundle_name.instance_1
…
vm_name.package_name.service_bundle_name.instance_n
Le nom de la VM n'est pas explicitement déclaré dans la configuration. Étant donné que la configuration est définie par VM, le nom de la VM est toujours celui de la VM sur laquelle le fichier de configuration est déployé et est déjà connu de l'agent d'orchestration.
Configurer les instances
La déclaration d'instances de bundle de services n'a aucun effet. Pour être exécutées par l'orchestrateur, les instances doivent être configurées. Par exemple, l'orchestrateur doit être informé des conditions (ou de l'état de la VM ou du véhicule) dans lesquelles une instance doit s'exécuter. Pour configurer des instances, les états de configuration doivent être définis par le biais des éléments suivants :
conditionest une expression sur l'état de la VM ou du véhicule qui doit être évaluée.instances_statesest un ensemble d'états par instance qui doivent être appliqués si la condition renvoietrue.
Pour en savoir plus, consultez les Conditions d'utilisation.
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"
}
}
}
Mappage des instances aux groupes
Vous pouvez également configurer des instances de service en les incluant dans des groupes de services. Au niveau de la configuration d'un bundle de services, vous pouvez ajouter des instances à des groupes. Vous pouvez ensuite configurer des groupes au niveau de la configuration de la VM. Pour en savoir plus, consultez la section suivante et Packs de services.
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"
}
}
Schéma proto
Voici un exemple de schéma 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;
}
Configuration au niveau de la VM
La configuration de la VM permet de définir les mappages de groupes et la configuration des groupes. Il est utilisé pour modéliser les dépendances entre les groupes de services au niveau d'une VM, ce qui permet de modifier l'état de plusieurs groupes de services en même temps. Toutes les instances d'un groupe sont placées dans l'état spécifié.
Orchestrator ne garantit pas l'ordre dans lequel le changement d'état est exécuté. L'orchestrateur fait passer chaque instance à l'état donné.
Les groupes sont déclarés de manière implicite en utilisant le nom group dans l'une des parties de la configuration. Par exemple, le mappage d'instance à groupe, le mappage de groupe à groupe et les états de configuration de groupe.
Mappage de groupe à groupe
Les groupes peuvent contenir d'autres groupes. En déclarant que group_1 contient subgroup_2, nous ajoutons effectivement toutes les instances de service de subgroup_2 à group_1.
Exemple :
# Declare that body contains fog_light and flasher_light.
group_mapping {
group: "body"
subgroup: "fog_light"
subgroup: "flasher_light"
}
Configurer un groupe
La déclaration d'un groupe n'a aucun effet. Pour être exécutés par l'orchestrateur, les groupes doivent être configurés. Par exemple, l'orchestrateur doit être informé des conditions ou de l'état de la VM ou du véhicule dans lesquels les groupes doivent s'exécuter.
Vous pouvez configurer des groupes de la même manière que les instances de service, c'est-à-dire en utilisant des états de configuration. La seule différence est l'utilisation de groups_states au lieu de instances_states dans la syntaxe :
state {
condition {
power_state: "ON"
}
groups_states {
started: "Body"
started: "Adas"
}
}
Schéma proto
Voici un exemple de schéma 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;
}
États de configuration
Les états de configuration (états) définissent le moment où une instance ou un groupe de services est démarré, arrêté ou détruit. Ils se composent de conditions et instances_states (configuration du bundle) et de groups_states (configuration de la VM).
Conditions
Les conditions permettent au modèle d'appliquer l'état d'instance défini lorsqu'une condition booléenne est évaluée à true. Une condition présente les caractéristiques suivantes :
Expression booléenne arbitrairement complexe (formée avec des expressions
andounot) basée sur des signaux compatibles tels que le mode d'alimentation, le véhicule et le mode personnalisé.(Facultatif) : l'état de configuration sans condition est toujours actif, ce qui signifie qu'il est évalué sur
true.
États des instances et des groupes
instances_states et groups_states présentent les caractéristiques suivantes.
Indiquez les états dont l'agent d'orchestration a besoin pour s'appliquer aux instances ou groupes donnés, étant donné que l'état est
active.Lorsque vous appliquez un état au groupe, il s'applique à chaque instance de bundle de services du groupe. Aucun ordre n'est appliqué pour déterminer quand les instances sont mises à l'état.
Voici les états acceptés :
startedaprès l'appel deService::on_start.createdaprès l'appel de
Service::new, mais avant celui deService::on_start.OU
après l'appel de
Service::on_stop, mais avant celui deService::drop.
destroyedaprès l'appel deService::drop.
Ensemble de règles
L'état d'une configuration peut être actif ou inactif, selon la condition. Plusieurs états peuvent être actifs à tout moment. Lorsqu'un agent d'orchestration reçoit une mise à jour du signal, tous les états de configuration sont évalués avant de modifier le cycle de vie des groupes de services. L'état des instances de service est évalué selon les règles suivantes :
Lorsque aucun des états actifs ne s'applique à l'instance de service, celle-ci est détruite.
Lorsque un ou plusieurs états actifs s'appliquent, la priorité est la suivante :
destroyeda une priorité absolue.startedest prioritaire surcreated.
Schéma proto
Voici un exemple de schéma 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;
}
Stratégie de récupération et de redémarrage en cas de plantage
L'orchestrateur fournit un mécanisme robuste pour gérer les plantages de bundle de services et les échecs de transition du cycle de vie. L'orchestrateur étant le composant le plus adapté pour exécuter la stratégie de redémarrage et de réessai, car il dispose d'une vue globale des états de service et gère les transitions de mode. Le gestionnaire de cycle de vie (LM, Lifecycle Manager) signale les plantages du bundle de services à l'orchestrateur par le biais de notifications de fin de liaison. Pour éviter les appels de binder inutiles au LM, l'orchestrateur met en cache le dernier état de chaque bundle (qu'il ait réussi ou non) et n'applique pas de nouvelles transitions si le dernier état connu est identique à celui demandé.
Configuration des nouvelles tentatives
Vous pouvez définir la stratégie de redémarrage et de nouvelle tentative par instance dans la configuration de votre Orchestrator à l'aide de retry_mapping. Si max_retries n'est pas défini dans la configuration, la valeur par défaut est extraite de la propriété système ro.boot.sdv.orchestrator.recovery.max_retries. Si cette propriété n'est pas définie, la valeur par défaut est 0.
max_retries: définit le nombre de fois où Orchestrator retente une transition après un échec temporaire ou une notification de plantage de bundle. Le compteur de tentatives est réinitialisé sur la valeur demax_retriesaprès une opération réussie ou lorsqu'un nouveau mode est traité. Si plusieurs mappages ciblent la même instance, celui dont lemax_retriesest le plus élevé est prioritaire.
Exemple de configuration
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
}
}
}
Comportement de récupération
La logique de redémarrage et de nouvelle tentative de l'orchestrateur gère correctement plusieurs scénarios d'échec :
- Plantage en fonctionnement normal : si un bundle de services plante lors de son exécution, l'orchestrateur applique la stratégie de redémarrage et tente de ramener le bundle à son dernier état demandé en fonction des nouvelles tentatives restantes.
- Plantage lors de la transition de mode : si un bundle a planté lors de l'application d'un nouveau mode, la demande de redémarrage est mise en file d'attente et traitée ultérieurement. Une fois la demande traitée, l'orchestrateur vérifie le dernier état de l'instance et n'applique le redémarrage que si l'instance n'est pas dans le dernier état demandé (à partir de la dernière transition de mode).
- Nouveau mode pendant la récupération : si l'orchestrateur reçoit une demande de transition vers un nouveau mode pendant le redémarrage d'un bundle (ou s'il se trouve dans la file d'attente des instances à redémarrer), il annule la récupération en cours. La nouvelle transition de mode prend le relais et le compteur de tentatives est réinitialisé pour permettre un nouvel ensemble de tentatives pour le nouvel état cible.
L'orchestrateur fait la distinction entre les différents types d'erreurs renvoyés par le gestionnaire de cycle de vie pour déterminer la stratégie de nouvelle tentative :
- Erreurs temporaires (
SERVICE_NOT_FOUND,OPERATION_FAILED,INTERNAL_ERROR) : l'orchestrateur réessaie l'opération sans effectuer d'action de nettoyage spéciale. - Erreurs persistantes (
VALUE_CORRUPTED,INVALID_ARGUMENT) : l'orchestrateur suppose que le bundle de services peut être dans un état corrompu et tente d'arrêter l'instance de service avant de réessayer l'opération pour assurer un redémarrage propre. - Erreurs permanentes (
PERMISSION_DENIED) : l'opération n'est pas retentée et le bundle est considéré comme étant dans un état irrécupérable.
Si le Lifecycle Manager plante, tous les processus du bundle de services sont perdus. Étant donné que l'état réel est inconnu, l'orchestrateur invalide chaque instance et applique une stratégie de redémarrage avec les tentatives restantes pour ramener chaque instance au dernier état demandé.
Pour éviter les boucles de récupération infinies pour les bundles qui plantent ou échouent à plusieurs reprises, le compteur de tentatives n'est réinitialisé à max_retries qu'après la réussite d'une opération de cycle de vie ou lorsqu'une nouvelle transition de mode est demandée. Si un bundle épuise ses tentatives en raison d'échecs consécutifs (par exemple, un échec de transition suivi d'un plantage), il n'est pas redémarré tant que le compteur de tentatives n'est pas réinitialisé.
Rapports d'état au Health Monitor
Orchestrator expose une interface de binder interne à laquelle le Health Monitor (HM) s'enregistre, ce qui lui permet de recevoir des informations à jour en continu sur l'état de tous les bundles de services. Grâce à cette interface, l'outil d'orchestration signale activement les deux éléments suivants :
- État du cycle de vie : état prévu de l'instance en fonction de la configuration actuelle et des modes actifs (par exemple, démarré, créé ou détruit).
- État de récupération : état de la tentative d'atteinte de l'état de cycle de vie prévu. Indique si l'instance est opérationnelle, si elle effectue actuellement une nouvelle tentative après un échec ou si elle n'a pas pu récupérer après avoir épuisé toutes les tentatives.
Ces informations sont signalées pour toutes les instances, y compris celles qui ne sont pas enregistrées pour être surveillées par des signaux de présence. HM utilise ces informations pour implémenter ses API afin de signaler l'état de la VM. Pour en savoir plus, consultez Surveillance de la santé.
Exemples
Cette section présente des exemples de configuration d'états avec des conditions.
Exemple de service de base
- Ne comporte aucune condition et est donc toujours active.
- Démarre une seule instance de service.
state {
# Note: This state has no condition, hence its actions are valid throughout the lifetime of the program
instances_states { started: "ServiceBundleName" }
}
Exemple d'application CVC
Condition : actif lorsque
custom_state != occupancy.OCCUPANCY_EMPTY || custom_state == preheat.PREHEAT_ON.Déclare plusieurs instances de service liées au CVC comme
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"
}
}
Exemple d'économie d'énergie
Condition : actif lorsque
custom_state == system_power.SYSTEM_POWER_LOW && custom_state == range_ext.RANGE_EXT_ON.Cet état peut être considéré comme un état d'économie d'énergie.
Déclare une instance de service liée au CVC comme
destroyed.Dans cet exemple, lorsque les modes
SYSTEM_POWER_LOWetRANGE_EXT_ONsont actifs, l'application CVC s'exécute sans l'instance de serviceRefrigerantLoop: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" } }
Exemple de vie à bord
Condition : actif si
power_state == ON && vehicle_state == LIFE_ON_BOARD.Cet état peut être considéré comme Quelqu'un est dans la voiture et celle-ci est allumée.
Déclare que les capteurs de température sont en cours d'exécution.
Lorsque quelqu'un se trouve dans la voiture, des éléments tels que la température sont surveillés pour des raisons de sécurité.
state {
condition {
and {
power_state: "ON"
vehicle_state: "LIFE_ON_BOARD"
}
}
# Temperature monitoring services
instances_states {
started: "TempSensorDriverZone"
started: "TempSensorPassengerZone"
}
}
Exemples
Cette section présente des exemples complets contenant :
Configuration proto au niveau du bundle de services, qui présente un bundle de services avec deux instances, chacune faisant partie d'un groupe
Configuration proto au niveau de la VM introduisant une logique d'interaction avec les groupes en fonction des modes
Configuration au niveau du bundle de services
# 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"
}
}
Configuration au niveau de la VM
# 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"
}
}
Configurer le parallélisme de la gestion des bundles
La propriété système ro.boot.sdv.max_bundles_management_threads est un paramètre de réglage clé pour contrôler les performances et la consommation de ressources lors des opérations du cycle de vie du bundle de services. Il définit le niveau maximal de parallélisme pour les transactions de forfaits de services et affecte directement deux services principaux :
Moteur d'orchestration : ce service lit la propriété pour déterminer le nombre d'appels simultanés (par exemple,
startService,stopService) que l'orchestrateur peut effectuer auprès du gestionnaire de cycle de vie. C'est essentiel pour les performances lors du démarrage et des transitions de mode, où de nombreux bundles peuvent changer d'état simultanément.Lifecycle Manager : ce service utilise la valeur de la propriété pour calculer la taille de son pool de threads Binder, qui est responsable du traitement de toutes les requêtes entrantes. Cela garantit que le LM dispose de suffisamment de threads pour gérer les requêtes simultanées de l'orchestrateur.
Si cette propriété n'est pas définie, les deux services utilisent par défaut la valeur 12.
Méthode de configuration
Vous pouvez définir la propriété dans le fichier BoardConfig.mk de votre appareil en l'ajoutant à la variable BOARD_BOOTCONFIG. Cela garantit que la valeur est appliquée chaque fois que l'appareil démarre.
BOARD_BOOTCONFIG += \
androidboot.sdv.max_bundles_management_threads=8
Pour modifier la valeur de votre appareil, modifiez cette ligne dans le fichier BoardConfig.mk approprié et recompilez.
Optimisation du temps de démarrage
ro.sdv.orchestrator.state.ready est une propriété booléenne write-once qui fait partie d'une stratégie d'optimisation des performances au démarrage. Cela indique que l'agent d'orchestration a terminé son initialisation et est prêt à commencer à gérer le cycle de vie des packs de services. Son objectif principal est de hiérarchiser le démarrage de l'orchestrateur et de ses packs de services gérés en contrôlant la séquence de démarrage des autres agents SDV.
- Défini par : l'agent d'orchestration.
- Quand : une fois pendant la séquence de démarrage.
- Utilisation : cette propriété est utilisée par le système d'initialisation pour contrôler la séquence de démarrage de la plupart des agents SDV (Updates Manager, fournisseur VSIDL, Health Monitor, Service Discovery, Data Tunnel, RPC, VPM et télémétrie). En démarrant l'outil d'orchestration de manière anticipée et en demandant aux autres agents d'attendre cette propriété, le système s'assure que l'outil d'orchestration peut commencer sa tâche essentielle de démarrage des packs de services sans entrer en concurrence pour les ressources système.
Performances
Lors du démarrage du système, le lancement simultané de tous les agents peut entraîner une contention des ressources, ce qui ralentit le processus de démarrage global. Pour limiter ce problème, un ordre de démarrage séquentiel est appliqué à l'aide des propriétés système :
- Registre des groupes de services : démarre en premier pour charger toutes les métadonnées des groupes de services.
- Lifecycle Manager et Orchestrator : ces agents principaux démarrent dès que le registre est prêt. Ce démarrage anticipé est essentiel, car il permet à l'outil d'orchestration de commencer immédiatement à évaluer sa configuration et à se préparer à démarrer les packs de services.
- Autres agents SDV : ne démarrent qu'une fois l'orchestrateur prêt.
Cette séquence contrôlée garantit que l'outil d'orchestration a la priorité pour utiliser les ressources système afin de démarrer les packs de services le plus tôt possible, ce qui permet un démarrage du système plus rapide, plus déterministe et plus efficace.
Modes consommés par Orchestrator
L'agent d'orchestration maintient un abonnement actif aux modes du véhicule et d'alimentation transmis par le VPM. Lors de l'établissement de la connexion initiale entre l'orchestrateur et le système de gestion de l'alimentation et du véhicule (VPM), l'orchestrateur définit les propriétés système booléennes suivantes sur true :
sdv.orchestrator.bootup.power_mode.readysdv.orchestrator.bootup.vehicle_mode.ready
En utilisant un fichier de configuration comme référence, l'agent d'orchestration calcule dynamiquement l'ensemble des bundles de services qui doivent être en état d'exécution en fonction des valeurs actuelles des modes reçus. L'orchestrateur communique ensuite avec le gestionnaire du cycle de vie, en émettant différentes commandes pour aligner l'état réel des bundles de services sur l'état cible calculé.
États du véhicule et de l'alimentation
L'agent VPM (Vehicle mode and power management) permet aux composants SDV d'être informés de l'état actuel du véhicule, comme le mode de fonctionnement (par exemple, en mode Parking ou Conduite) et l'état de l'alimentation (par exemple, Activé et Suspendu). L'orchestrateur évalue ces valeurs pour définir les bundles de services à exécuter en fonction de sa configuration. Pour en savoir plus, consultez Gestion du véhicule et de l'alimentation.
Modes personnalisés
Étant donné leur nombre, nous ne pouvons pas modéliser tous les modes de véhicules. Chaque OEM a des besoins différents et la standardisation des modes de véhicule ne peut pas répondre à tous les cas d'utilisation des OEM. Par conséquent, nous acceptons les modes spécifiques aux OEM, appelés modes personnalisés. Ces modes n'étendent pas les modes de véhicule et d'alimentation existants. Au lieu de cela, ils permettent de définir de nouveaux modes.
Fonctionnalité :
Portée globale : les modes personnalisés sont globaux et s'appliquent de manière uniforme à toutes les VM gérées par l'orchestrateur.
Composition : chaque modification du mode personnalisé se compose de deux éléments :
Nom : identifiant unique sélectionné par l'OEM pour représenter le mode personnalisé.
Valeur : état actuel du mode personnalisé, qui peut être
UNDEFINEDlorsqu'aucune valeur n'est définie.
Rôle d'orchestrateur : l'orchestrateur agit en tant que récepteur passif des valeurs de mode personnalisé.
Rôle du bundle de services : chaque bundle de services peut posséder plusieurs modes personnalisés et publier de nouvelles valeurs dans n'importe quel mode. Plusieurs offres groupées de services peuvent posséder le même mode personnalisé, ce qui signifie qu'un mode personnalisé peut recevoir de nouvelles valeurs provenant de différentes sources.
Responsabilité de la validation : les OEM sont responsables de la validité des transitions d'état. L'orchestrateur accepte toute nouvelle valeur.
Caractéristiques estimées :
Nombre estimé : les modes d'alimentation et de véhicule gèrent le cycle de vie de la plupart des groupes de services, les modes personnalisés jouant un rôle supplémentaire. Nous nous attendons à ce que l'ordre de grandeur des modes personnalisés soit de l'ordre de la dizaine et non de la centaine.
Timing estimé : les modes ne sont pas envoyés périodiquement. Au lieu de cela, les modes sont déclenchés par des événements spécifiques, tels que l'ouverture d'une porte, le lancement d'une séquence de stationnement, le début d'un cycle de recharge et d'autres événements similaires d'importance définie par l'OEM.
La conception du mode personnalisé offre la flexibilité nécessaire pour définir et gérer des modes spécifiques tout en permettant à l'orchestrateur de rester indépendant de la logique de la machine à états sous-jacente.
Modes compatibles
Pour s'assurer que les bundles de services ne sont publiés que dans les modes personnalisés dont ils sont propriétaires, chacun d'eux doit déclarer explicitement la liste des modes personnalisés détenus dans sa configuration Orchestrator, qui est disponible dans la VM locale avec le registre des bundles de services. Les tentatives de publication dans un mode personnalisé non déclaré sont ignorées.
Pour déclarer les modes personnalisés qu'un bundle de services est autorisé à publier (et donc à posséder), le schéma proto service_bundle_config est étendu avec les éléments suivants :
// 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;
}
Configurer des bundles en fonction des modes
La configuration proto Orchestrator existante (composant Condition) permet de manipuler les bundles de services en fonction de modes personnalisés :
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;
}
Exemple de fichier .proto
L'exemple suivant montre comment configurer des instances d'un bundle de services pour qu'elles démarrent en fonction d'un état TURN et 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"
}
}
}
Définir de nouveaux modes personnalisés
Le processus de définition d'une nouvelle valeur de mode personnalisé commence par le bundle de services, qui communique la valeur souhaitée à l'orchestrateur local exécuté sur la même VM. L'orchestrateur vérifie ensuite que le bundle de services dispose des autorisations nécessaires pour publier dans le mode personnalisé spécifié, en se référant à la configuration définie dans .textproto pour déterminer s'il doit propager la valeur à d'autres VM. Une fois la propagation effectuée, chaque Orchestrator examine sa configuration pour trouver la liste des groupes de services dont l'état doit être modifié.
RPC
Chaque Orchestrator exécuté sur chaque VM crée un serveur RPC pour écouter les nouvelles valeurs du mode personnalisé. Chaque bundle de services souhaitant mettre à jour un mode personnalisé doit créer un client RPC sur le serveur. Les LCA sont appliquées pour empêcher les bundles non autorisés de se connecter au serveur.
La définition du fichier .proto pour définir une nouvelle valeur via RPC ressemble à l'exemple suivant :
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) {};
}
Annulation des transitions d'alimentation
L'orchestrateur permet d'annuler les transitions d'alimentation en cours via le mode d'alimentation SHUTDOWN_CANCELLED (envoyé par le VPM à l'orchestrateur).
Prenons l'exemple de configuration Orchestrator suivant :
state {
condition {
power_state: "SUSPEND_TO_RAM_ENTER"
}
instances_states {
started: "instance-1"
started: "instance-2"
started: "instance-3"
}
}
Lorsque l'Orchestrator reçoit un mode SHUTDOWN_CANCELLED, son comportement est régi par deux scénarios principaux. Dans les deux cas, le mode d'alimentation SHUTDOWN_CANCELLED est ajouté à la fin de la file d'attente. SHUTDOWN_CANCELLED est ensuite exécuté après que les éléments mis en file d'attente ont été consommés.
Scénario 1 : Le mode en cours est un mode d'alimentation
Si l'orchestrateur exécute une mise à jour du mode d'alimentation, une annulation du mode en cours est demandée. Bien que le gestionnaire de cycle de vie ne prenne pas en charge l'annulation d'une transition en cours, l'orchestrateur vérifie qu'aucune nouvelle demande de bundle de services n'est lancée.
Exemple : Si instance-1 de la configuration de l'exemple précédent est en cours de démarrage lorsque le mode SHUTDOWN_CANCELLED est reçu, instance-1 termine son démarrage. Toutefois, instance-2 et instance-3 ne passent pas à l'état "démarré".
Scénario 2 : Un mode d'alimentation existe dans la file d'attente de traitement
Si l'orchestrateur traite une mise à jour du mode non lié à l'alimentation et qu'une demande d'alimentation figure dans la file d'attente des modes à exécuter, la transition d'alimentation est supprimée de la file d'attente. Cela empêche son exécution.
Exemple : En utilisant la configuration de l'exemple précédent, si l'orchestrateur travaille sur une mise à jour non liée à l'alimentation (comme une mise à jour du véhicule) et que SUSPEND_TO_RAM_ENTER est dans la file d'attente, la réception de SHUTDOWN_CANCELLED n'entraîne le démarrage d'aucune des instances (instance-1, instance-2, instance-3).
Exemple d'implémentation
Le catalogue d'un client qui souhaite utiliser le code généré par le middleware pour créer un client sur le serveur RPC peut ressembler à cet exemple :
# 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"
}
}
Lorsque vous générez du code, vous devez ajouter la dépendance au catalogue Orchestrator :
--dependency-catalog-path orchestration/engine/stable/vsidl/*
Le code client permettant d'envoyer une nouvelle valeur se présente comme suit :
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
Outils de débogage
L'agent Orchestrator est compatible avec l'outil dumpsys. Pour l'appeler, exécutez la commande suivante sur une instance SDV en cours d'exécution :
adb shell dumpsys com.google.sdv.ISdvAgent/orch
Utilisez cet outil pour déboguer l'état interne de l'agent Orchestrator et obtenir des informations à son sujet. Les éléments suivants s'affichent :
- État des modes actuels : affichez les modes véhicule, alimentation et personnalisés actifs.
- Éditeurs de modes personnalisés : identifiez les services qui peuvent publier des modes personnalisés (et les modes concernés).
- État requis par service : découvrez l'état de chaque pack de services en fonction des conditions prédéfinies et des modes actuels. Cela permet de diagnostiquer pourquoi un service peut ne pas être dans l'état attendu.
- État de l'application du mode : obtenez une vue claire d'un mode forcé en cours ou du dernier mode forcé si aucun n'est en cours.
- File d'attente du mode d'application : affichez les modes en attente d'application.
Exemple :
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: []
----------------
Pour en savoir plus sur les bundles de services individuels gérés par l'orchestrateur, utilisez les dumpsys existants du gestionnaire de cycle de vie comme suit :
dumpsys google.sdv.lifecycle.ILifecycleManager/default
Vous obtiendrez ainsi des informations détaillées sur l'état du cycle de vie de chaque service. En combinant la sortie dumpsys d'Orchestrator avec la sortie de Lifecycle Manager, vous obtenez une image complète du cycle de vie des bundles de services dans la VM.