L'orchestratore è un agente SDV locale che viene eseguito su ogni macchina virtuale (VM) e fornisce un meccanismo per controllare quando i bundle di servizi devono essere creati, avviati, arrestati o eliminati. Ciò avviene tramite una configurazione di orchestrazione, in cui definisci un insieme di regole che determinano quando e come vengono eseguite le azioni sulle istanze dei bundle di servizi. Queste regole si basano su modalità personalizzate, di alimentazione e del veicolo.
Puoi configurare l'orchestratore in APEX di configurazione o tramite configurazioni per VM. Questo sistema di configurazione distribuita consente di aggiornare in modo indipendente le parti di ogni pacchetto di servizi tramite il registro dei pacchetti di servizi, come illustrato qui.
Figura 1. Diagramma di configurazione dell'orchestratore.
Le configurazioni indipendenti dal veicolo non cambiano a seconda dell'OEM o del veicolo. La configurazione rimane invariata su tutti i veicoli di ciascun OEM. Le configurazioni specifiche per il veicolo possono variare a seconda del veicolo e dell'OEM, anche se la configurazione potrebbe essere la stessa per tutti i veicoli realizzati da un OEM specifico.
APEX di configurazione
In fase di runtime, l'orchestratore accede al registro dei service bundle per recuperare un'orchestrazione SDV per ogni service bundle, caricando e analizzando ogni configurazione. Per saperne di più, consulta la sezione Metadati di orchestrazione.
Configurazione per VM
Quando Orchestrator viene avviato, carica e analizza la configurazione della VM (se presente). Il percorso assoluto di questo file di configurazione è specificato tramite le proprietà di sistema persist.sdv.orchestrator_config_path e ro.boot.sdv.orchestrator_config_path.
Il sistema determina il percorso del file di configurazione della VM all'avvio in base alla seguente gerarchia:
Il sistema controlla la proprietà
persist.sdv.orchestrator_config_path. Se ha un valore, viene utilizzato quel percorso. Questo valore viene mantenuto dopo i riavvii o impostato in fase di runtime.Se il campo
persist.sdv.orchestrator_config_pathè vuoto, il sistema controlla la proprietàro.boot.sdv.orchestrator_config_path. Se la proprietàro.boot.sdvha un valore, il percorso viene copiato nella proprietà persist e utilizzato per l'avvio corrente e tutti gli avvii futuri (a meno che non venga sostituito).
persist.sdv.orchestrator_config_path
persist.sdv.orchestrator_config_path è la proprietà principale utilizzata dall'agente orchestratore SDV
per ottenere il percorso del file di configurazione. Si tratta di una
proprietà persistente, il che significa che il suo valore viene salvato dopo i riavvii del dispositivo. Puoi
modificare il valore in fase di runtime, il che è utile per i test o per scenari specifici
(ad esempio, test end-to-end).
Puoi impostare il valore in fase di runtime utilizzando il comando setprop e in fase di compilazione
utilizzando un makefile (con l'estensione .mk) o un file di script delle risorse, con l'estensione
.rc.
Impostare la proprietà in fase di runtime
L'impostazione della proprietà in fase di runtime è utile per i test o per apportare modifiche temporanee, poiché il valore viene salvato tra i riavvii:
adb root
adb shell setprop persist.sdv.orchestrator_config_path {$path_to_file}.textproto
Impostare la proprietà al tempo di compilazione
Per impostare questa proprietà come parte della configurazione di compilazione del dispositivo, aggiungi una riga al makefile del prodotto o della scheda. Questa impostazione è ideale per impostare un valore predefinito per una nuova immagine del dispositivo.
# Add this line to a product's or device's .mk file
PRODUCT_PROPERTY_OVERRIDES += persist.sdv.orchestrator_config_path={$path_to_file}.textproto
Puoi anche impostare questa proprietà all'interno di un file di script delle risorse:
# 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 è una proprietà di sola lettura all'avvio utilizzata per fornire un valore iniziale per la proprietà persist.sdv.orchestrator_config_path. Se persist.sdv.orchestrator_config_path è vuoto all'avvio del sistema, il valore di ro.boot.sdv.orchestrator_config_path viene copiato. Una volta
impostato persist.sdv.orchestrator_config_path, non verrà sovrascritto da
questa proprietà nei riavvii successivi.
Puoi impostare ro.boot.sdv.orchestrator_config_path utilizzando bootconfig o la
riga di comando del kernel.
Formato file
Definisci la configurazione dell'orchestrazione in formato .textproto (ad esempio, in
testo strutturato) in modo che le nuove configurazioni possano essere caricate in fase di runtime.
Sintassi di configurazione
Questa sezione descrive la sintassi di configurazione.
Pacchetti di servizi
Ogni bundle di servizi deve essere definito con la configurazione del bundle di servizi, che identifica il bundle all'interno dell'orchestratore e viene utilizzata per gestire il ciclo di vita dell'istanza del bundle. La configurazione del bundle di servizi definisce:
InstanceToGroupMappingti consente di includere un'istanza del pacchetto di servizi in un gruppo per stabilire dipendenze tra le istanze dello stesso pacchetto di servizi.InstancesStatesdefinisce i diversi stati dell'istanza del pacchetto di servizi.InstancesStateConfigurationdefinisce lo stato (daInstancesStates) che deve essere impostato per un'istanza di bundle di servizi se la condizione restituiscetrue.ServiceBundleConfigcontiene informazioni sul bundle di servizi specifico e sulle relative istanze. Per il bundle, contiene i rispettiviInstanceToGroupMappingeInstancesStateConfiguration.CustomModesdefinisce un elenco di modalità personalizzate che il bundle può pubblicare.CustomModesviene utilizzato per impedire a un bundle non autorizzato di modificare il valore di una modalità personalizzata. Questo campo è facoltativo, in quanto il pacchetto di servizi potrebbe non essere pubblicato in alcuna modalità personalizzata. Per saperne di più, consulta Modalità personalizzate.
Configurazione del bundle obbligatoria
Come minimo, la configurazione del bundle fornisce questi attributi:
service_bundle_config {
package_name: "package_name"
service_bundle_name: "service_bundle_name"
instance: "instance_1"
instance: "instance_n"
}
Questa dichiarazione definisce le istanze del bundle di servizi n con i rispettivi FQIN:
vm_name.package_name.service_bundle_name.instance_1
…
vm_name.package_name.service_bundle_name.instance_n
Il nome della VM non è dichiarato esplicitamente nella configurazione. Poiché la configurazione è definita per VM, il nome della VM è sempre il nome della VM a cui viene distribuito il file di configurazione ed è già noto all'agente di orchestrazione.
Configura le istanze
La dichiarazione delle istanze del bundle di servizi non ha alcun effetto. Per essere eseguite da Orchestrator, le istanze devono essere configurate. Ad esempio, l'orchestratore deve essere informato delle condizioni (o dello stato della VM o del veicolo) in cui deve essere eseguita un'istanza. Per configurare le istanze, gli stati di configurazione devono essere definiti tramite:
conditionè un'espressione sullo stato della VM o del veicolo che deve essere valutata.instances_statesè un insieme di stati per istanza da applicare se la condizione restituisce il valoretrue.
Per saperne di più, consulta Condizioni.
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"
}
}
}
Mappatura da istanza a gruppo
Puoi anche configurare le istanze di servizio includendole nei gruppi di servizi. A livello di configurazione del bundle di servizi, puoi aggiungere istanze ai gruppi. Puoi quindi configurare i gruppi a livello di configurazione VM. Per saperne di più, consulta la sezione successiva e Pacchetti di servizi.
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"
}
}
Schema proto
Ecco un esempio di schema 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;
}
Configurazione a livello di VM
La configurazione della VM consente di definire le mappature dei gruppi e la configurazione per i gruppi. Viene utilizzato per modellare le dipendenze tra i bundle di servizi a livello di VM, offrendo così la flessibilità di modificare lo stato di più bundle di servizi contemporaneamente. Tutte le istanze di un gruppo vengono portate allo stato specificato.
Orchestrator non garantisce l'ordine in cui viene eseguita la modifica dello stato. L'orchestratore promuove ogni istanza allo stato specificato.
I gruppi vengono dichiarati implicitamente utilizzando il nome group in una qualsiasi delle parti di configurazione. Ad esempio, il mapping da istanza a gruppo, il mapping da gruppo a gruppo
e gli stati di configurazione dei gruppi.
Mappatura da gruppo a gruppo
I gruppi possono contenere altri gruppi. Dichiarando che group_1 contiene subgroup_2, aggiungiamo effettivamente tutte le istanze di servizio da subgroup_2 a group_1.
Ad esempio:
# Declare that body contains fog_light and flasher_light.
group_mapping {
group: "body"
subgroup: "fog_light"
subgroup: "flasher_light"
}
Configurare un gruppo
La dichiarazione di un gruppo non ha effetto. Per essere eseguiti dall'agente di orchestrazione, i gruppi devono essere configurati. Ad esempio, l'orchestratore deve essere informato in quali condizioni o stato della VM o del veicolo devono essere eseguiti i gruppi.
Puoi configurare i gruppi in modo simile alle istanze di servizio, ovvero utilizzando gli stati di configurazione. L'unica differenza è l'utilizzo di groups_states
anziché di instances_states nella sintassi:
state {
condition {
power_state: "ON"
}
groups_states {
started: "Body"
started: "Adas"
}
}
Schema proto
Ecco un esempio di schema 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;
}
Stati di configurazione
Gli stati di configurazione definiscono quando un'istanza o un gruppo di servizi viene avviato, arrestato o eliminato e sono costituiti da conditions e
instances_states (configurazione del bundle) e groups_states (configurazione della VM).
Condizioni
Le condizioni consentono al modello una condizione booleana in base alla quale, se valutata come
true, viene applicato lo stato dell'istanza definito. Una condizione ha le seguenti
caratteristiche:
Espressione booleana arbitrariamente complessa (formata con espressioni
andonot) basata su indicatori supportati come alimentazione, veicolo e modalità personalizzata.(Facoltativo) Lo stato di configurazione senza una condizione è sempre attivo, il che significa che restituisce
true
Stati delle istanze e stati dei gruppi
instances_states e groups_states hanno queste caratteristiche.
Specifica gli stati necessari all'agente di orchestrazione da applicare alle istanze o ai gruppi specificati, dato che lo stato è
activeQuando applichi uno stato al gruppo, questo viene applicato a ogni istanza del pacchetto di servizi nel gruppo. Non viene applicato alcun ordine per quanto riguarda il momento in cui le istanze vengono portate allo stato.
Gli stati supportati includono:
starteddopo la chiamata aService::on_start.createddopo la chiamata di
Service::new, ma prima di quella diService::on_start.OPPURE
dopo la chiamata di
Service::on_stop, ma prima di quella diService::drop.
destroyeddopo la chiamata aService::drop.
Set di regole
Uno stato di configurazione può essere attivo o non attivo, a seconda della condizione. È possibile attivare più stati in qualsiasi momento. Quando un agente di orchestrazione riceve un aggiornamento del segnale, vengono valutati tutti gli stati di configurazione prima di modificare il ciclo di vita dei bundle di servizi. Gli stati delle istanze di servizio vengono valutati in base a queste regole:
Quando nessuno degli stati attivi si applica all'istanza del servizio, questa viene eliminata.
Quando si applicano uno o più stati attivi, viene applicata questa precedenza:
destroyedha la precedenza assoluta.startedha la precedenza sucreated.
Schema proto
Ecco un esempio di schema 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;
}
Strategia di ripristino e riavvio in caso di arresto anomalo
L'agente di orchestrazione fornisce un meccanismo solido per la gestione degli arresti anomali dei bundle di servizi e degli errori di transizione del ciclo di vita. Poiché l'orchestratore ha una visione olistica degli stati del servizio e gestisce le transizioni di modalità, è il componente più adatto per eseguire la strategia di riavvio e ripetizione. Il servizio di report di Lifecycle Manager (LM) segnala gli arresti anomali del bundle di servizi a Orchestrator tramite notifiche di interruzione del binder. Per evitare chiamate binder non necessarie al LM, l'orchestratore memorizza nella cache l'ultimo stato di ogni bundle (riuscito o meno) e non riapplica le transizioni se l'ultimo stato noto è uguale a quello nuovo richiesto.
Configurazione nuovi tentativi
Puoi definire la strategia di riavvio e ripetizione per istanza nella configurazione di Orchestrator utilizzando retry_mapping. Se max_retries non è impostato nella
configurazione, il valore predefinito viene preso dalla
proprietà di sistema ro.boot.sdv.orchestrator.recovery.max_retries. Se questa
proprietà non è impostata, il valore di riserva è 0.
max_retries: definisce il numero di tentativi di transizione dell'orchestratore dopo un errore temporaneo o una notifica di arresto anomalo del bundle. Il contatore dei tentativi viene reimpostato sul valore dimax_retriesdopo un'operazione riuscita o quando viene elaborata una nuova modalità. Se più mappature hanno come target la stessa istanza, ha la precedenza quella con il valoremax_retriespiù alto.
Esempio di configurazione
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
}
}
}
Comportamento di recupero
La logica di riavvio e riprova di Orchestrator gestisce correttamente diversi scenari di errore:
- Arresto anomalo del normale funzionamento: se un bundle di servizi si arresta in modo anomalo durante l'esecuzione, l'orchestratore applica la strategia di riavvio e tenta di riportare il bundle all'ultimo stato richiesto in base ai tentativi rimanenti.
- Arresto anomalo durante la transizione di modalità: se un bundle ha subito un arresto anomalo durante l'applicazione di una nuova modalità, la richiesta di riavvio viene messa in coda ed elaborata in un secondo momento. Una volta elaborata la richiesta, Orchestrator controlla qual è stato l'ultimo stato dell'istanza e applica il riavvio solo se l'istanza non si trova nell'ultimo stato richiesto (dall'ultima transizione di modalità).
- Nuova modalità durante il ripristino: se l'orchestratore riceve una richiesta di transizione a una nuova modalità mentre un bundle viene riavviato (o si trova nella coda delle istanze da riavviare), annulla il ripristino in corso. La nuova transizione di modalità prende il sopravvento e il contatore dei tentativi viene reimpostato per consentire un nuovo set di tentativi per il nuovo stato di destinazione.
Orchestrator distingue tra diversi tipi di errori restituiti da Lifecycle Manager per determinare la strategia di ripetizione:
- Errori temporanei (
SERVICE_NOT_FOUND,OPERATION_FAILED,INTERNAL_ERROR): l'orchestratore riprova l'operazione senza eseguire alcuna azione di pulizia speciale. - Errori permanenti (
VALUE_CORRUPTED,INVALID_ARGUMENT): Orchestrator presuppone che il bundle di servizi possa essere in uno stato danneggiato e tenta di terminare l'istanza del servizio prima di riprovare l'operazione per garantire un riavvio pulito. - Errori permanenti (
PERMISSION_DENIED): l'operazione non viene ritentata e il bundle viene considerato in uno stato non recuperabile.
Se Lifecycle Manager si arresta in modo anomalo, tutti i processi del pacchetto di servizi vengono persi. Poiché lo stato effettivo è sconosciuto, Orchestrator invalida ogni istanza e applica una strategia di riavvio con i tentativi rimanenti per portare ogni istanza allo stato richiesto più recente.
Per evitare loop di ripristino infiniti per i bundle che si arrestano in modo anomalo o non riescono ripetutamente,
il contatore dei tentativi viene reimpostato su max_retries solo dopo che un'operazione del ciclo di vita
va a buon fine o quando viene richiesta una nuova transizione di modalità. Se un bundle esaurisce i
tentativi a causa di errori consecutivi (ad esempio, un errore di transizione seguito
da un arresto anomalo), non viene riavviato finché il contatore dei tentativi non viene reimpostato.
Report sullo stato al monitoraggio dell'integrità
L'orchestratore espone un'interfaccia di binder interna a cui si registra Health Monitor (HM), consentendogli di ricevere aggiornamenti continui sullo stato di tutti i bundle di servizi. Tramite questa interfaccia, l'agente di orchestrazione segnala attivamente sia:
- Stato del ciclo di vita:lo stato previsto dell'istanza in base alla configurazione attuale e alle modalità attive (ad esempio avviata, creata o eliminata).
- Stato di ripristino:lo stato del raggiungimento dello stato del ciclo di vita previsto, che indica se l'istanza è operativa, se sta riprovando dopo un errore o se il ripristino non è riuscito dopo aver esaurito tutti i tentativi.
Queste informazioni vengono riportate per tutte le istanze, incluse quelle che non sono state registrate per il monitoraggio heartbeat. HM utilizza queste informazioni per implementare le proprie API per segnalare lo stato della VM. Per saperne di più, consulta la sezione Monitoraggio della salute.
Esempi
Questa sezione presenta esempi di configurazione degli stati con condizioni.
Esempio di servizio di base
- Non ha condizioni ed è quindi sempre attivo.
- Avvia una singola istanza di servizio.
state {
# Note: This state has no condition, hence its actions are valid throughout the lifetime of the program
instances_states { started: "ServiceBundleName" }
}
Esempio di app per impianti HVAC
Condizione: attivo quando
custom_state != occupancy.OCCUPANCY_EMPTY || custom_state == preheat.PREHEAT_ON.Dichiara più istanze di servizio correlate all'impianto HVAC come
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"
}
}
Esempio di risparmio energetico
Condizione: attivo quando
custom_state == system_power.SYSTEM_POWER_LOW && custom_state == range_ext.RANGE_EXT_ON.Questo stato può essere considerato uno stato di risparmio energetico.
Dichiara un'istanza di servizio correlata all'impianto HVAC come
destroyed.In questo esempio, quando le modalità
SYSTEM_POWER_LOWeRANGE_EXT_ONsono attive, l'app HVAC viene eseguita senza l'istanza del servizioRefrigerantLoop: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" } }
Esempio di vita a bordo
Condizione: attivo se
power_state == ON && vehicle_state == LIFE_ON_BOARD.Questo stato può essere visualizzato come Qualcuno è in auto e l'auto è accesa.
Dichiara che i sensori di temperatura sono in esecuzione.
Quando qualcuno si trova in auto, vengono monitorati elementi come la temperatura per motivi di sicurezza.
state {
condition {
and {
power_state: "ON"
vehicle_state: "LIFE_ON_BOARD"
}
}
# Temperature monitoring services
instances_states {
started: "TempSensorDriverZone"
started: "TempSensorPassengerZone"
}
}
Esempi
Questa sezione presenta esempi completi contenenti:
Una configurazione proto a livello di bundle di servizi che introduce un bundle di servizi con due istanze, ciascuna parte di un gruppo
Una configurazione proto a livello di VM che introduce la logica per interagire con i gruppi in base alle modalità
Configurazione a livello di pacchetto di servizi
# 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"
}
}
Configurazione a livello di 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"
}
}
Configura il parallelismo della gestione dei bundle
La proprietà di sistema ro.boot.sdv.max_bundles_management_threads è un parametro di ottimizzazione chiave per controllare le prestazioni e il consumo di risorse durante le operazioni del ciclo di vita del bundle di servizi. Definisce il livello massimo di parallelismo
per le transazioni dei bundle di servizi e influisce direttamente su due servizi principali:
Orchestration Engine:questo servizio legge la proprietà per determinare il numero di chiamate simultanee (ad esempio
startService,stopService) che Orchestrator può effettuare a Lifecycle Manager. Ciò è fondamentale per le prestazioni durante l'avvio e le transizioni di modalità in cui molti bundle potrebbero cambiare stato contemporaneamente.Lifecycle Manager:questo servizio utilizza il valore della proprietà per calcolare le dimensioni del pool di thread Binder, responsabile della gestione di tutte le richieste in entrata. In questo modo, l'LM dispone di thread sufficienti per gestire le richieste simultanee dell'orchestratore.
Se questa proprietà non è impostata, entrambi i servizi utilizzano per impostazione predefinita il valore 12.
Metodo di configurazione
Puoi impostare la proprietà nel file BoardConfig.mk del dispositivo aggiungendola alla
variabile BOARD_BOOTCONFIG. In questo modo, il valore viene applicato ogni volta
che il dispositivo si avvia.
BOARD_BOOTCONFIG += \
androidboot.sdv.max_bundles_management_threads=8
Per modificare il valore per il tuo dispositivo, modifica questa riga nel file
BoardConfig.mk appropriato e ricompila.
Ottimizzazione del tempo di avvio
ro.sdv.orchestrator.state.ready è una proprietà booleana write-once che fa parte di una strategia di ottimizzazione delle prestazioni all'avvio. Indica che l'agente di orchestrazione ha completato l'inizializzazione ed è pronto per iniziare a gestire il ciclo di vita dei bundle di servizi. Il suo scopo principale è dare la priorità
all'avvio di Orchestrator e dei relativi bundle di servizi gestiti controllando
la sequenza di avvio di altri agenti SDV.
- Impostato da:l'agente di orchestrazione.
- Quando:una volta durante la sequenza di avvio.
- Utilizzo:questa proprietà viene utilizzata dal sistema init per controllare la sequenza di avvio della maggior parte degli agenti SDV (Updates Manager, VSIDL provider, Health Monitor, Service Discovery, Data Tunnel, RPC, VPM e Telemetry). Avviando l'orchestratore in anticipo e facendo in modo che gli altri agenti attendano questa proprietà, il sistema garantisce che l'orchestratore possa iniziare la sua attività critica di avvio dei bundle di servizi senza competere per le risorse di sistema.
Rendimento
Durante l'avvio del sistema, l'avvio simultaneo di tutti gli agenti può portare a una contesa delle risorse, rallentando l'intero processo di avvio. Per risolvere questo problema, viene applicato un ordine di avvio sequenziale utilizzando le proprietà di sistema:
- Registro dei bundle di servizi: inizia per caricare tutti i metadati dei bundle di servizi.
- Lifecycle Manager e Orchestrator:questi agenti principali vengono avviati non appena il registry è pronto. Questo inizio anticipato è fondamentale perché consente all'orchestratore di iniziare a valutare la sua configurazione e prepararsi ad avviare immediatamente i bundle di servizi.
- Altri agenti SDV:vengono avviati solo dopo che l'orchestratore è pronto.
Questa sequenza controllata garantisce che Orchestrator abbia la priorità di utilizzare le risorse di sistema per avviare i bundle di servizi il prima possibile, il che porta a un avvio del sistema più rapido, deterministico ed efficiente.
Modalità utilizzate dall'agente di orchestrazione
L'agente di orchestrazione mantiene un abbonamento attivo alle modalità del veicolo e di alimentazione
trasmesse dal VPM. Una volta stabilita la connessione iniziale tra l'orchestratore e il sistema di gestione dell'alimentazione e del veicolo (VPM), l'orchestratore imposta le seguenti proprietà di sistema booleane su true:
sdv.orchestrator.bootup.power_mode.readysdv.orchestrator.bootup.vehicle_mode.ready
Utilizzando un file di configurazione come riferimento, l'agente di orchestrazione calcola dinamicamente l'insieme di bundle di servizi che devono essere in stato di esecuzione in base ai valori correnti delle modalità ricevute. L'orchestratore comunica quindi con il gestore del ciclo di vita, emettendo comandi diversi per allineare lo stato effettivo dei bundle di servizi allo stato di destinazione calcolato.
Stati del veicolo e dell'alimentazione
L'agente di gestione della modalità veicolo e dell'alimentazione (VPM) consente ai componenti SDV di essere informati sullo stato attuale del veicolo, ad esempio la modalità operativa (ad esempio in modalità di parcheggio o guida) e lo stato di alimentazione (ad esempio On e Suspend). L'orchestratore valuta questi valori per definire quali bundle di servizi devono essere eseguiti in base alla configurazione dell'orchestratore. Per scoprire di più, vedi Gestione del veicolo e dell'alimentazione.
Modalità personalizzate
Data la loro quantità, non possiamo modellare tutte le modalità del veicolo. Ogni OEM ha esigenze diverse e la standardizzazione delle modalità del veicolo non può soddisfare tutti i casi d'uso degli OEM. Di conseguenza, supportiamo modalità specifiche per OEM, note come modalità personalizzate. Queste modalità non estendono le modalità di alimentazione e di guida esistenti. ma forniscono un modo per definire nuove modalità.
Funzionalità:
Ambito globale: le modalità personalizzate sono globali e si applicano in modo uniforme a tutte le VM gestite dall'orchestratore.
Composizione:ogni modifica della modalità personalizzata è costituita da due elementi:
Nome:identificatore univoco selezionato dall'OEM per rappresentare la modalità personalizzata.
Valore:lo stato attuale della modalità personalizzata, che può essere
UNDEFINEDquando non è impostato alcun valore.
Ruolo di orchestratore:l'orchestratore funge da ricevitore passivo dei valori della modalità personalizzata.
Ruolo del pacchetto di servizi:ogni pacchetto di servizi può avere più modalità personalizzate e può pubblicare nuovi valori in qualsiasi modalità. Più pacchetti di servizi possono avere la stessa modalità personalizzata, il che significa che una modalità personalizzata può ricevere nuovi valori da origini diverse.
Responsabilità di convalida: gli OEM sono responsabili di garantire transizioni di stato valide. Orchestrator accetta qualsiasi nuovo valore.
Caratteristiche stimate:
Conteggio stimato:le modalità di alimentazione e del veicolo gestiscono il ciclo di vita della maggior parte dei bundle di servizi, mentre le modalità personalizzate svolgono un ruolo supplementare. Prevediamo che l'ordine di grandezza delle modalità personalizzate sia di decine e non di centinaia.
Tempistiche stimate:le modalità non vengono inviate periodicamente. Al contrario, le modalità sono basate su eventi, attivate da azioni specifiche come l'apertura di una portiera, l'avvio di una sequenza di parcheggio, l'inizio di un ciclo di ricarica e altri eventi simili di importanza definita dall'OEM.
La progettazione della modalità personalizzata offre la flessibilità di definire e gestire modalità specifiche consentendo a Orchestrator di rimanere indipendente dalla logica della macchina a stati sottostante.
Modalità supportate
Per garantire che i bundle di servizi vengano pubblicati solo nelle modalità personalizzate di proprietà, ognuno deve dichiarare esplicitamente l'elenco delle modalità personalizzate di proprietà all'interno della configurazione di Orchestrator, disponibile nella VM locale con il registro dei bundle di servizi. I tentativi di pubblicazione in una modalità personalizzata non dichiarata vengono ignorati.
Per dichiarare le modalità personalizzate che un bundle di servizi è autorizzato a pubblicare (e quindi
possiede), lo schema proto service_bundle_config viene esteso con quanto segue:
// 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;
}
Configurare i bundle in base alle modalità
La configurazione proto di Orchestrator esistente (il componente Condition)
supporta la manipolazione dei bundle di servizi in base a modalità personalizzate:
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;
}
Esempio di proto
L'esempio seguente mostra come configurare le istanze di un bundle di servizi in modo che vengano avviate in base a uno stato TURN e 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"
}
}
}
Impostare nuove modalità personalizzate
La procedura di impostazione di un nuovo valore della modalità personalizzata inizia con il pacchetto di servizi,
che comunica il valore desiderato all'orchestratore locale in esecuzione sulla
stessa VM. L'orchestratore verifica quindi che il bundle di servizi disponga delle
autorizzazioni necessarie per la pubblicazione nella modalità personalizzata specificata, facendo riferimento alla
configurazione definita in .textproto, per determinare se deve propagare
il valore ad altre VM. Una volta propagato, ogni Orchestrator esamina la propria configurazione per trovare l'elenco dei bundle di servizi per i quali deve essere modificato lo stato.
RPC
Ogni Orchestrator in esecuzione su ogni VM crea un server RPC per rilevare nuovi valori della modalità personalizzata. Ogni pacchetto di servizi che vuole aggiornare una modalità personalizzata deve creare un client RPC per il server. Gli ACL vengono applicati per impedire ai bundle non autorizzati di connettersi al server.
La definizione proto per impostare un nuovo valore tramite RPC è simile a questo esempio:
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) {};
}
Annullamento delle transizioni di alimentazione
L'orchestratore consente l'annullamento delle transizioni di alimentazione in corso tramite
la modalità di alimentazione SHUTDOWN_CANCELLED (inviata da VPM all'orchestratore).
Considera la seguente configurazione di Orchestrator come esempio:
state {
condition {
power_state: "SUSPEND_TO_RAM_ENTER"
}
instances_states {
started: "instance-1"
started: "instance-2"
started: "instance-3"
}
}
Quando viene ricevuta una modalità SHUTDOWN_CANCELLED, due scenari principali determinano il comportamento di Orchestrator. In entrambi i casi, la modalità di risparmio energetico SHUTDOWN_CANCELLED viene aggiunta alla fine della coda. SHUTDOWN_CANCELLED viene eseguito dopo
che gli elementi in coda sono stati utilizzati.
Scenario 1: la modalità corrente è una modalità di risparmio energetico
Se l'orchestratore sta eseguendo un aggiornamento della modalità di alimentazione, viene richiesta l'annullamento della modalità in corso. Sebbene Lifecycle Manager non supporti intrinsecamente l'annullamento di una transizione in corso, Orchestrator verifica che non vengano avviate nuove richieste di bundle di servizi.
Esempio: se instance-1 della configurazione nell'esempio precedente è in
fase di avvio quando viene ricevuta la modalità SHUTDOWN_CANCELLED,
instance-1 completa l'avvio. Tuttavia, instance-2 e instance-3 non
procedono con le transizioni allo stato avviato.
Scenario 2: nella coda di elaborazione è presente una modalità di risparmio energetico
Nel caso in cui l'orchestratore stia elaborando un aggiornamento della modalità non di alimentazione e nella coda delle modalità da eseguire sia presente una richiesta di alimentazione, la transizione di alimentazione viene rimossa dalla coda. In questo modo, l'esecuzione viene impedita.
Esempio: utilizzando la configurazione dell'esempio precedente, se Orchestrator sta
lavorando a un aggiornamento non correlato all'alimentazione (ad esempio un aggiornamento del veicolo) e
SUSPEND_TO_RAM_ENTER è in coda, la ricezione di SHUTDOWN_CANCELLED comporta
l'avvio di nessuna delle istanze (instance-1, instance-2, instance-3).
Esempio di implementazione
Il catalogo per un client che vuole utilizzare il codice generato dal middleware per creare un client per il server RPC può essere simile a questo esempio:
# 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"
}
}
Quando generi il codice, devi aggiungere la dipendenza al catalogo Orchestrator:
--dependency-catalog-path orchestration/engine/stable/vsidl/*
Il codice client per inviare un nuovo valore è simile al seguente:
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
Strumenti di debug
L'agente Orchestrator supporta lo strumento dumpsys. Puoi richiamarlo eseguendo il seguente comando su un'istanza SDV in esecuzione:
adb shell dumpsys com.google.sdv.ISdvAgent/orch
Utilizza questo strumento per eseguire il debug e ottenere informazioni sullo stato interno dell'agente Orchestrator. In questo modo, viene visualizzato:
- Stato attuale delle modalità:visualizza le modalità personalizzate, di alimentazione e del veicolo attive.
- Editori in modalità personalizzata: identifica i servizi che possono pubblicare modalità personalizzate (e in quali modalità).
- Stato richiesto per servizio:scopri lo stato di ogni pacchetto di servizi in base alle condizioni predefinite e alle modalità attuali. Questo aiuta a diagnosticare il motivo per cui un servizio potrebbe non essere nello stato previsto.
- Stato della modalità di applicazione forzata:ottieni un quadro chiaro di una modalità di applicazione forzata in corso o dell'ultima modalità di applicazione forzata se non è in corso.
- Coda di applicazione forzata della modalità: visualizza le modalità in attesa di essere applicate.
Ad esempio:
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: []
----------------
Per scoprire di più sui bundle di servizi individuali gestiti da Orchestrator, utilizza il dumpsys esistente di Lifecycle Manager nel seguente modo:
dumpsys google.sdv.lifecycle.ILifecycleManager/default
In questo modo, vengono fornite informazioni dettagliate sullo stato del ciclo di vita di ciascun servizio. La combinazione dell'output di dumpsys di Orchestrator con l'output di Lifecycle Manager presenta un quadro completo del ciclo di vita dei bundle di servizi nella VM.