Orchestrator konfigurieren

Der Orchestrator ist ein lokaler SDV-Agent, der auf jeder VM ausgeführt wird und einen Mechanismus zum Steuern des Zeitpunkts bereitstellt, zu dem Dienst-Bundles erstellt, gestartet, beendet oder zerstört werden sollen. Dies erfolgt über eine Orchestrierungskonfiguration, in der Sie eine Reihe von Regeln definieren, die festlegen, wann und wie Aktionen für Servicebündelinstanzen ausgeführt werden. Diese Regeln basieren auf Fahrzeug-, Energie- und benutzerdefinierten Modi.

Sie können den Orchestrator in Konfigurations-APEXs oder über Konfigurationen pro VM konfigurieren. Dieses verteilte Konfigurationssystem ermöglicht es, Teile jedes Dienst-Bundles unabhängig über die Service Bundle Registry zu aktualisieren, wie hier dargestellt.

Diagramm der verteilten Orchestrator-Konfiguration

Abbildung 1. Diagramm der Orchestrator-Konfiguration.

Fahrzeugunabhängige Konfigurationen ändern sich nicht je nach OEM oder Fahrzeug. Die Konfiguration bleibt bei allen Fahrzeugen des jeweiligen OEM gleich. Fahrzeugspezifische Konfigurationen können sich bei verschiedenen Fahrzeugen von verschiedenen OEMs unterscheiden. Die Konfiguration kann jedoch für alle Fahrzeuge eines bestimmten OEMs gleich sein.

Konfigurations-APEX-Module

Zur Laufzeit ruft der Orchestrator aus der Dienstbündelregistrierung eine SDV-Orchestrierung für jedes Dienstbündel ab und lädt und parst jede Konfiguration. Weitere Informationen finden Sie unter Orchestrierungsmetadaten.

Pro VM-Konfiguration

Wenn der Orchestrator startet, wird die VM-Konfiguration (falls vorhanden) geladen und geparst. Der absolute Pfad zu dieser Konfigurationsdatei wird über die Systemattribute persist.sdv.orchestrator_config_path und ro.boot.sdv.orchestrator_config_path angegeben.

Das System bestimmt den Pfad der VM-Konfigurationsdatei beim Booten anhand der folgenden Hierarchie:

  1. Das System prüft das Attribut persist.sdv.orchestrator_config_path. Wenn er einen Wert hat, wird dieser Pfad verwendet. Dieser Wert bleibt auch nach einem Neustart erhalten oder wird zur Laufzeit festgelegt.

  2. Wenn persist.sdv.orchestrator_config_path leer ist, prüft das System das Attribut ro.boot.sdv.orchestrator_config_path. Wenn das Attribut ro.boot.sdv einen Wert hat, wird dieser Pfad in das Attribut „persist“ kopiert und für den aktuellen und alle zukünftigen Starts verwendet, sofern er nicht überschrieben wird.

persist.sdv.orchestrator_config_path

persist.sdv.orchestrator_config_path ist die primäre Eigenschaft, die vom SDV Orchestrator-Agent verwendet wird, um den Pfad zu seiner Konfigurationsdatei abzurufen. Dies ist eine dauerhafte Eigenschaft, d. h. ihr Wert wird auch nach einem Neustart des Geräts gespeichert. Sie können den Wert zur Laufzeit ändern. Das ist nützlich für Tests oder bestimmte Szenarien (z. B. Ende-zu-Ende-Tests).

Sie können den Wert zur Laufzeit mit dem Befehl setprop und zur Build-Zeit mit einer Makefile-Datei (mit der Erweiterung .mk) oder einer Ressourcenscriptdatei mit der Erweiterung .rc festlegen.

Property zur Laufzeit festlegen

Das Festlegen der Property zur Laufzeit ist nützlich für Tests oder vorübergehende Änderungen, da der Wert über Neustarts hinweg gespeichert wird:

adb root
adb shell setprop persist.sdv.orchestrator_config_path {$path_to_file}.textproto

Attribut zur Build-Zeit festlegen

Wenn Sie diese Property als Teil der Build-Konfiguration Ihres Geräts festlegen möchten, fügen Sie der Make-Datei Ihres Produkts oder Boards eine Zeile hinzu. Das ist ideal, um einen Standardwert für ein neues Gerätebild festzulegen.

# Add this line to a product's or device's .mk file
PRODUCT_PROPERTY_OVERRIDES += persist.sdv.orchestrator_config_path={$path_to_file}.textproto

Sie können diese Eigenschaft auch in einer Ressourcenscriptdatei festlegen:

# 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 ist ein schreibgeschütztes Attribut, das beim Starten des Geräts gelesen wird und mit dem ein Anfangswert für das Attribut persist.sdv.orchestrator_config_path bereitgestellt wird. Wenn persist.sdv.orchestrator_config_path beim Systemstart leer ist, wird der Wert von ro.boot.sdv.orchestrator_config_path dorthin kopiert. Sobald persist.sdv.orchestrator_config_path festgelegt wurde, wird es bei nachfolgenden Starts nicht durch diese Property überschrieben.

Sie können ro.boot.sdv.orchestrator_config_path mit der Bootkonfiguration oder der Kernel-Befehlszeile festlegen.

Dateiformat

Definieren Sie die Orchestrierungskonfiguration im .textproto-Format (z. B. in strukturiertem Text), damit neue Konfigurationen zur Laufzeit geladen werden können.

Konfigurationssyntax

In diesem Abschnitt wird die Konfigurationssyntax beschrieben.

Servicepakete

Jedes Dienst-Bundle muss mit der Dienst-Bundle-Konfiguration definiert werden. Diese identifiziert das Bundle im Orchestrator und wird verwendet, um den Lebenszyklus der Bundle-Instanz zu verwalten. In der Konfiguration des Dienstpakets wird Folgendes definiert:

  • Mit InstanceToGroupMapping können Sie eine Instanz des Dienstbündels in eine Gruppe einfügen, um Abhängigkeiten zwischen Instanzen desselben Dienstbündels herzustellen.

  • InstancesStates definiert die verschiedenen Status für die Dienstbündelinstanz.

  • InstancesStateConfiguration definiert den Status (aus InstancesStates), auf den eine Dienstpaketinstanz gesetzt werden muss, wenn die Bedingung als true ausgewertet wird.

  • ServiceBundleConfig enthält Informationen zum jeweiligen Service-Bundle und seinen Instanzen. Es enthält für das Bundle die entsprechenden InstanceToGroupMapping und InstancesStateConfiguration.

  • CustomModes definiert eine Liste benutzerdefinierter Modi, die für das Bundle veröffentlicht werden dürfen. CustomModes wird verwendet, um zu verhindern, dass ein nicht autorisiertes Bundle den Wert eines benutzerdefinierten Modus ändert. Dieses Feld ist optional, da das Dienstpaket möglicherweise nicht in einem benutzerdefinierten Modus veröffentlicht wird. Weitere Informationen finden Sie unter Benutzerdefinierte Modi.

Erforderliche Bundle-Konfiguration

Die Bundle-Konfiguration enthält mindestens die folgenden Attribute:

service_bundle_config {
    package_name: "package_name"
    service_bundle_name: "service_bundle_name"

    instance: "instance_1"
    instance: "instance_n"
}

Mit dieser Deklaration werden n-Service-Bundle-Instanzen mit den entsprechenden FQINs definiert:

vm_name.package_name.service_bundle_name.instance_1

vm_name.package_name.service_bundle_name.instance_n

Der VM-Name ist in der Konfiguration nicht explizit deklariert. Da die Konfiguration pro VM definiert wird, ist der VM-Name immer der Name der VM, auf der die Konfigurationsdatei bereitgestellt wird, und dem Orchestrierungs-Agent bereits bekannt.

Instanzen konfigurieren

Die Deklaration von Dienstbündelinstanzen hat keine Auswirkungen. Damit Instanzen vom Orchestrator ausgeführt werden können, müssen sie konfiguriert sein. Der Orchestrator muss beispielsweise darüber informiert werden, unter welchen Bedingungen (oder welchem Status der VM oder des Fahrzeugs) eine Instanz ausgeführt werden soll. Konfigurationsstatus für die Konfiguration von Instanzen sollten über Folgendes definiert werden:

  • condition ist ein Ausdruck für den VM- oder Fahrzeugstatus, der ausgewertet werden soll.

  • instances_states ist eine Reihe von Status pro Instanz, die angewendet werden sollen, wenn die Bedingung true ergibt.

Weitere Informationen finden Sie unter Bedingungen.

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

Zuordnung von Instanzen zu Gruppen

Sie können Dienstinstanzen auch konfigurieren, indem Sie sie in Dienstgruppen einfügen. Auf der Ebene der Dienstpaketkonfiguration können Sie Gruppen Instanzen hinzufügen. Anschließend können Sie Gruppen auf VM-Konfigurationsebene konfigurieren. Weitere Informationen finden Sie im nächsten Abschnitt und unter Dienstpakete.

service_bundle_config {
    package_name: "oem.package"
    service_bundle_name: "OemApplication"

    instance: "fog_front_light"
    instance: "fog_rear_light"
    instance: "turn_signal_light"
    instance: "light_flasher_display"

    # Declare that fog_light contains fog_front_light and fog_rear_light.
    group_mapping {
        group: "fog_light"
        instance: "fog_front_light"
        instance: "fog_rear_light"
    }

    # Declare that flasher_light contains turn_signal_light and light_flasher_display.
    group_mapping {
        group: "flasher_light"
        instance: "turn_signal_light"
        instance: "light_flasher_display"
    }
}

Proto-Schema

Hier ein Beispiel für ein Protoschema:

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

Konfiguration auf VM-Ebene

Mit der VM-Konfiguration können Sie Gruppenzuordnungen und die Konfiguration für Gruppen definieren. Damit lassen sich Abhängigkeiten zwischen Service-Bundles auf VM-Ebene modellieren. So können Sie den Status mehrerer Service-Bundles gleichzeitig ändern. Alle Instanzen einer Gruppe werden in den angegebenen Status versetzt.

Der Orchestrator garantiert nicht die Reihenfolge, in der die Statusänderung ausgeführt wird. Der Orchestrator sorgt dafür, dass jede Instanz den angegebenen Status erreicht.

Gruppen werden implizit deklariert, indem der Name group in einem der Konfigurationsteile verwendet wird. Dazu gehören beispielsweise die Zuordnung von Instanzen zu Gruppen, die Zuordnung von Gruppen zu Gruppen und die Konfigurationsstatus von Gruppen.

Gruppen-zu-Gruppen-Zuordnung

Gruppen können andere Gruppen enthalten. Wenn wir deklarieren, dass group_1 subgroup_2 enthält, fügen wir effektiv alle Dienstinstanzen aus subgroup_2 zu group_1 hinzu.

Beispiel:

# Declare that body contains fog_light and flasher_light.
group_mapping {
    group: "body"
    subgroup: "fog_light"
    subgroup: "flasher_light"
}

Gruppe konfigurieren

Das Deklarieren einer Gruppe hat keine Auswirkungen. Damit Gruppen vom Orchestrator ausgeführt werden können, müssen sie konfiguriert werden. Der Orchestrator muss beispielsweise darüber informiert werden, unter welchen Bedingungen oder in welchem Zustand der VM oder des Fahrzeugs die Gruppen ausgeführt werden sollen.

Sie können Gruppen auf ähnliche Weise wie Dienstinstanzen konfigurieren, nämlich mithilfe von Konfigurationsstatus. Der einzige Unterschied ist die Verwendung von groups_states anstelle von instances_states in der Syntax:

state {
    condition {
        power_state: "ON"
    }

    groups_states {
        started: "Body"
        started: "Adas"
    }
}

Proto-Schema

Hier ein Beispiel für ein Proto-Schema:

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

Konfigurationsstatus

Konfigurationsstatus (Status) definieren, wann eine Dienstinstanz oder -gruppe gestartet, beendet oder zerstört wird. Sie bestehen aus conditions und instances_states (Bundle-Konfiguration) und groups_states (VM-Konfiguration).

Bedingungen

Mit Bedingungen kann dem Modell eine boolesche Bedingung vorgegeben werden, unter der der definierte Instanzstatus angewendet wird, wenn sie zu true ausgewertet wird. Eine Bedingung hat folgende Eigenschaften:

  • Beliebig komplexer boolescher Ausdruck (gebildet mit and- oder not-Ausdrücken) basierend auf unterstützten Signalen wie Stromversorgung, Fahrzeug und benutzerdefiniertem Modus.

  • (Optional) Der Konfigurationsstatus ohne Bedingung ist immer aktiv, d. h., er wird als true ausgewertet.

Instanzstatus und Gruppenstatus

instances_states und groups_states haben die folgenden Eigenschaften.

  • Gibt an, welche Zustände der Orchestrierungs-Agent für die angegebenen Instanzen oder Gruppen benötigt, wenn der Zustand active ist.

  • Wenn Sie einen Status auf die Gruppe anwenden, gilt er für jede Dienstpaketinstanz in der Gruppe. Es gibt keine bestimmte Reihenfolge, in der Instanzen in den Status versetzt werden.

Folgende Bundesstaaten werden unterstützt:

  • started nach dem Aufruf von Service::on_start.

  • created

    • nachdem Service::new aufgerufen wurde, aber bevor Service::on_start aufgerufen wird.

      ODER

    • nachdem Service::on_stop aufgerufen wurde, aber bevor Service::drop aufgerufen wird.

  • destroyed nach dem Aufruf von Service::drop.

Regelsatz

Der Konfigurationsstatus kann je nach Bedingung entweder aktiv oder inaktiv sein. Es können jederzeit mehrere Status aktiv sein. Wenn ein Orchestrierungs-Agent eine Signalaktualisierung empfängt, werden alle Konfigurationsstatus ausgewertet, bevor der Lebenszyklus von Service-Bundles geändert wird. Dienstinstanzstatus werden gemäß diesen Regeln ausgewertet:

  • Wenn keiner der aktiven Status auf die Serviceinstanz zutrifft, wird sie zerstört.

  • Wenn ein oder mehrere aktive Status zutreffen, gilt folgende Priorität:

    1. destroyed hat absolute Priorität.
    2. started hat Vorrang vor created.

Proto-Schema

Hier ein Beispiel für ein Proto-Schema:

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

Strategie für die Wiederherstellung nach einem Absturz und den Neustart

Der Orchestrator bietet einen robusten Mechanismus zur Behandlung von Abstürzen von Dienstbündeln und Fehlern bei der Lebenszyklusumstellung. Da der Orchestrator einen ganzheitlichen Blick auf die Dienststatus hat und Modusübergänge verwaltet, ist er die am besten geeignete Komponente für die Ausführung der Neustart- und Wiederholungsstrategie. Der Lifecycle Manager (LM) meldet Abstürze von Service-Bundles über Binder-Death-Benachrichtigungen an den Orchestrator. Um unnötige Binder-Aufrufe an den LM zu vermeiden, speichert der Orchestrator den letzten Status jedes Bundles (unabhängig davon, ob er erfolgreich war oder nicht) im Cache und wendet keine Übergänge noch einmal an, wenn der letzte bekannte Status mit dem neuen angeforderten Status übereinstimmt.

Konfiguration wiederholen

Sie können die Neustart- und Wiederholungsstrategie pro Instanz in Ihrer Orchestrator-Konfiguration mit retry_mapping definieren. Wenn max_retries in der Konfiguration nicht festgelegt ist, wird der Standardwert aus der Systemeigenschaft ro.boot.sdv.orchestrator.recovery.max_retries übernommen. Wenn diese Eigenschaft nicht festgelegt ist, wird der Wert standardmäßig auf 0 gesetzt.

  • max_retries: Definiert, wie oft der Orchestrator einen Übergang nach einem vorübergehenden Fehler oder einer Benachrichtigung über einen Bundle-Absturz wiederholt. Der Wiederholungszähler wird nach einem erfolgreichen Vorgang oder bei der Verarbeitung eines neuen Modus auf den Wert von max_retries zurückgesetzt. Wenn mehrere Zuordnungen auf dieselbe Instanz ausgerichtet sind, hat die mit dem höchsten max_retries Vorrang.

Beispielkonfiguration

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

Wiederherstellungsverhalten

Die Neustart- und Wiederholungslogik des Orchestrators bewältigt mehrere Fehlerszenarien:

  • Absturz im Normalbetrieb: Wenn ein Dienst-Bundle während der Ausführung abstürzt, wendet der Orchestrator die Neustartstrategie an und versucht, das Bundle basierend auf den verbleibenden Wiederholungsversuchen in den zuletzt angeforderten Zustand zurückzubringen.
  • Absturz während des Modusübergangs: Wenn ein Bundle beim Erzwingen eines neuen Modus abstürzt, wird die Neustartanfrage in die Warteschlange gestellt und später verarbeitet. Sobald die Anfrage verarbeitet wurde, prüft der Orchestrator, welcher der letzte Status der Instanz war, und wendet den Neustart nur an, wenn sich die Instanz nicht im zuletzt angeforderten Status (aus dem letzten Modusübergang) befindet.
  • Neuer Modus während der Wiederherstellung: Wenn der Orchestrator eine Anfrage zum Wechseln in einen neuen Modus erhält, während ein Bundle neu gestartet wird (oder sich in der Warteschlange der neu zu startenden Instanzen befindet), wird die laufende Wiederherstellung abgebrochen. Die neue Modusumstellung wird übernommen und der Zähler für Wiederholungsversuche wird zurückgesetzt, um eine neue Reihe von Versuchen für den neuen Zielstatus zu ermöglichen.

Der Orchestrator unterscheidet zwischen verschiedenen Fehlertypen, die vom Lifecycle Manager zurückgegeben werden, um die Wiederholungsstrategie zu bestimmen:

  • Vorübergehende Fehler (SERVICE_NOT_FOUND, OPERATION_FAILED, INTERNAL_ERROR): Der Orchestrator wiederholt den Vorgang, ohne dass spezielle Bereinigungsmaßnahmen erforderlich sind.
  • Schwerwiegende Fehler (VALUE_CORRUPTED, INVALID_ARGUMENT): Der Orchestrator geht davon aus, dass sich das Dienst-Bundle in einem beschädigten Zustand befindet, und versucht, die Dienstinstanz zu beenden, bevor er den Vorgang noch einmal ausführt, um einen sauberen Neustart zu gewährleisten.
  • Schwerwiegende Fehler (PERMISSION_DENIED): Der Vorgang wird nicht wiederholt und das Bundle befindet sich in einem nicht behebaren Zustand.

Wenn der Lifecycle Manager abstürzt, gehen alle Prozesse des Dienst-Bundles verloren. Da der tatsächliche Status unbekannt ist, macht der Orchestrator jede Instanz ungültig und wendet eine Neustartstrategie mit verbleibenden Wiederholungsversuchen an, um jede Instanz in den zuletzt angeforderten Status zu versetzen.

Um endlose Wiederholungsschleifen für Bundles zu verhindern, die wiederholt abstürzen oder fehlschlagen, wird der Wiederholungszähler nur auf max_retries zurückgesetzt, wenn ein Lebenszyklusvorgang erfolgreich ist oder eine neue Modusübergabe angefordert wird. Wenn ein Bundle aufgrund aufeinanderfolgender Fehler (z. B. ein Übergangsfehler gefolgt von einem Absturz) alle Wiederholungsversuche aufgebraucht hat, wird es erst neu gestartet, wenn der Wiederholungszähler zurückgesetzt wurde.

Statusberichte an Health Monitor

Der Orchestrator stellt eine interne Binder-Schnittstelle zur Verfügung, bei der sich der Health Monitor (HM) registriert, damit er kontinuierliche Updates zum Status aller Dienstpakete erhält. Über diese Schnittstelle meldet der Orchestrator aktiv Folgendes:

  • Lebenszyklusstatus:Der beabsichtigte Status der Instanz basierend auf der aktuellen Konfiguration und den aktiven Modi (z. B. „gestartet“, „erstellt“ oder „zerstört“).
  • Wiederherstellungsstatus:Der Status des Erreichens des beabsichtigten Lebenszyklusstatus. Er gibt an, ob die Instanz betriebsbereit ist, derzeit nach einem Fehler wiederholt wird oder die Wiederherstellung nach Erschöpfung aller Wiederholungsversuche fehlgeschlagen ist.

Diese Informationen werden für alle Instanzen gemeldet, auch für solche, die nicht für die Heartbeat-Überwachung registriert wurden. HM verwendet diese Informationen, um seine APIs zu implementieren und den Status der VM zu melden. Weitere Informationen findest du unter Health Monitoring.

Beispiele

In diesem Abschnitt finden Sie Beispiele für die Konfiguration von Status mit Bedingungen.

Beispiel für Basisdienst
  • Hat keine Bedingung und ist daher immer aktiv.
  • Startet eine einzelne Dienstinstanz.
state {
  # Note: This state has no condition, hence its actions are valid throughout the lifetime of the program
  instances_states { started: "ServiceBundleName" }
}
HLK-App-Beispiel
  • Bedingung: Aktiv, wenn custom_state != occupancy.OCCUPANCY_EMPTY || custom_state == preheat.PREHEAT_ON.

  • Deklariert mehrere HLK-bezogene Dienstinstanzen als 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"
  }
}
Beispiel für Energiesparmodus
  • Bedingung: Aktiv, wenn custom_state == system_power.SYSTEM_POWER_LOW && custom_state == range_ext.RANGE_EXT_ON.

    Dieser Status kann als Energiesparmodus betrachtet werden.

  • Deklariert eine HLK-bezogene Dienstinstanz als destroyed.

  • In diesem Beispiel wird die HLK-App ohne die RefrigerantLoop-Dienstinstanz ausgeführt, wenn die Modi SYSTEM_POWER_LOW und RANGE_EXT_ON aktiv sind:

    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" }
    }
    
Beispiel für die Einrichtung
  • Bedingung: Aktiv, wenn power_state == ON && vehicle_state == LIFE_ON_BOARD.

    Dieser Status kann als Jemand ist im Auto und das Auto ist eingeschaltet angesehen werden.

  • Gibt an, dass Temperatursensoren ausgeführt werden.

  • Wenn sich jemand im Auto befindet, werden Elemente wie die Temperatur aus Sicherheitsgründen überwacht.

state {
  condition {
    and {
      power_state: "ON"
      vehicle_state: "LIFE_ON_BOARD"
    }
  }

  # Temperature monitoring services
  instances_states {
    started: "TempSensorDriverZone"
    started: "TempSensorPassengerZone"
  }
}

Beispiele

Dieser Abschnitt enthält vollständige Beispiele mit:

  • Eine Proto-Konfiguration auf Service-Bundle-Ebene, in der ein Service-Bundle mit zwei Instanzen eingeführt wird, die jeweils Teil einer Gruppe sind

  • Eine Proto-Konfiguration auf VM-Ebene, die Logik für die Interaktion mit den Gruppen basierend auf Modi enthält

Konfiguration auf Servicepaketebene

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

Konfiguration auf VM-Ebene

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

Parallelität der Paketverwaltung konfigurieren

Die System-Property ro.boot.sdv.max_bundles_management_threads ist ein wichtiger Abstimmungsparameter, um die Leistung und den Ressourcenverbrauch während der Lebenszyklusvorgänge des Service-Bundles zu steuern. Sie definiert die maximale Parallelität für Transaktionen von Service-Bundles und wirkt sich direkt auf zwei Hauptdienste aus:

  1. Orchestration Engine:Dieser Dienst liest die Property, um zu ermitteln, wie viele gleichzeitige Aufrufe (z. B. startService, stopService) der Orchestrator an den Lifecycle Manager senden kann. Das ist entscheidend für die Leistung beim Booten und bei Modusübergängen, bei denen sich der Status vieler Bundles gleichzeitig ändern kann.

  2. Lifecycle Manager:Dieser Dienst verwendet den Wert der Property, um die Größe des Binder-Thread-Pools zu berechnen, der für die Verarbeitung aller eingehenden Anfragen zuständig ist. So hat das Sprachmodell genügend Threads, um die gleichzeitigen Anfragen des Orchestrators zu verarbeiten.

Wenn diese Property nicht festgelegt ist, wird für beide Dienste standardmäßig der Wert 12 verwendet.

Konfigurationsmethode

Sie können das Attribut in der Datei BoardConfig.mk Ihres Geräts festlegen, indem Sie es der Variablen BOARD_BOOTCONFIG hinzufügen. So wird der Wert bei jedem Start des Geräts angewendet.

BOARD_BOOTCONFIG += \
    androidboot.sdv.max_bundles_management_threads=8

Wenn Sie den Wert für Ihr Gerät ändern möchten, bearbeiten Sie diese Zeile in der entsprechenden BoardConfig.mk-Datei und führen Sie den Build noch einmal aus.

Optimierung der Startzeit

ro.sdv.orchestrator.state.ready ist eine boolesche write-once-Property, die Teil einer Strategie zur Leistungsoptimierung beim Booten ist. Dies weist darauf hin, dass der Orchestration-Agent die Initialisierung abgeschlossen hat und bereit ist, den Lebenszyklus von Service-Bundles zu verwalten. Der Hauptzweck besteht darin, den Start des Orchestrators und der zugehörigen verwalteten Dienst-Bundles zu priorisieren, indem die Startreihenfolge anderer SDV-Agents gesteuert wird.

  • Festgelegt von:Orchestration-Agent.
  • Wann:Einmal während der Startsequenz.
  • Verwendung:Diese Property wird vom Init-System verwendet, um die Startsequenz der meisten SDV-Agents zu steuern (Updates Manager, VSIDL-Anbieter, Health Monitor, Service Discovery, Data Tunnel, RPC, VPM und Telemetry). Wenn der Orchestrator frühzeitig gestartet wird und andere Agenten auf diese Eigenschaft warten, kann der Orchestrator seine kritische Aufgabe, Dienstbündel zu starten, ohne Konkurrenz um Systemressourcen beginnen.

Leistung

Wenn während des Systemstarts alle Agents gleichzeitig gestartet werden, kann es zu Ressourcenkonflikten kommen, die den gesamten Startvorgang verlangsamen. Um dieses Problem zu beheben, wird eine sequenzielle Startreihenfolge mithilfe von Systemeigenschaften erzwungen:

  1. Service-Bundle-Registry:Wird zuerst gestartet, um alle Metadaten von Service-Bundles zu laden.
  2. Lifecycle Manager und Orchestrator:Diese Core-Agents werden gestartet, sobald die Registry bereit ist. Dieser frühe Start ist entscheidend, da der Orchestrator so seine Konfiguration auswerten und sich darauf vorbereiten kann, Dienstpakete sofort zu starten.
  3. Andere SDV-Agents:Werden erst gestartet, wenn der Orchestrator bereit ist.

Diese kontrollierte Sequenz sorgt dafür, dass der Orchestrator Priorität hat, Systemressourcen zu verwenden, um Dienstbündel so früh wie möglich zu starten. Dies führt zu einem schnelleren, deterministischeren und effizienteren Systemstart.

Vom Orchestrator verwendete Modi

Der Orchestrierungs-Agent unterhält ein aktives Abo für Fahrzeug- und Energiemodi, die vom VPM übertragen werden. Beim ersten Herstellen einer Verbindung zwischen dem Orchestrator und dem Vehicle and Power Management-System (VPM) legt der Orchestrator die folgenden booleschen Systemeigenschaften auf true fest:

  • sdv.orchestrator.bootup.power_mode.ready

  • sdv.orchestrator.bootup.vehicle_mode.ready

Anhand einer Konfigurationsdatei berechnet der Orchestrierungs-Agent dynamisch die Menge der Service-Bundles, die sich basierend auf den aktuellen Werten der empfangenen Modi in einem laufenden Zustand befinden sollten. Der Orchestrator kommuniziert dann mit dem Lifecycle Manager und gibt verschiedene Befehle aus, um den tatsächlichen Status der Service-Bundles an den berechneten Zielstatus anzugleichen.

Fahrzeug- und Energiestatus

Der VPM-Agent (Vehicle Mode and Power Management) ermöglicht es SDV-Komponenten, über den aktuellen Status des Fahrzeugs informiert zu werden, z. B. über den Betriebsmodus (z. B. „Parken“ oder „Fahren“) und den Energiestatus (z. B. „Ein“ und „Stand-by“). Der Orchestrator wertet diese Werte aus, um anhand der Orchestrator-Konfiguration festzulegen, welche Service-Bundles ausgeführt werden sollen. Weitere Informationen finden Sie unter Fahrzeug- und Energieverwaltung.

Benutzerdefinierte Modi

Aufgrund der großen Anzahl können wir nicht alle Fahrzeugmodi modellieren. Jeder OEM hat unterschiedliche Anforderungen und die Standardisierung von Fahrzeugmodi kann nicht alle OEM-Anwendungsfälle abdecken. Daher unterstützen wir OEM-spezifische Modi, die als benutzerdefinierte Modi bezeichnet werden. Diese Modi erweitern die vorhandenen Fahrzeug- und Energiemodi nicht. Stattdessen bieten sie eine Möglichkeit, neue Modi zu definieren.

Funktionen:

  • Globaler Bereich:Benutzerdefinierte Modi sind global und werden einheitlich auf alle vom Orchestrator verwalteten VMs angewendet.

  • Zusammensetzung:Jede benutzerdefinierte Modusänderung besteht aus zwei Elementen:

    • Name:Eindeutige Kennung, die vom OEM für den benutzerdefinierten Modus ausgewählt wurde.

    • Wert:Der aktuelle Status für den benutzerdefinierten Modus. Wenn kein Wert festgelegt ist, kann er UNDEFINED sein.

  • Orchestrator-Rolle:Der Orchestrator fungiert als passiver Empfänger von Werten für benutzerdefinierte Modi.

  • Rolle des Dienstpakets:Jedes Dienstpaket kann mehrere benutzerdefinierte Modi haben und neue Werte für jeden Modus veröffentlichen. Mehrere Service-Bundles können denselben benutzerdefinierten Modus haben. Das bedeutet, dass ein benutzerdefinierter Modus neue Werte aus verschiedenen Quellen empfangen kann.

  • Verantwortung für die Validierung:OEMs sind für die Validierung von Statusübergängen verantwortlich. Der Orchestrator akzeptiert jeden neuen Wert.

Geschätzte Merkmale:

  • Geschätzte Anzahl:Der Lebenszyklus der meisten Service-Bundles wird durch Energie- und Fahrzeugmodi verwaltet. Benutzerdefinierte Modi spielen dabei eine ergänzende Rolle. Wir gehen davon aus, dass die Anzahl der benutzerdefinierten Modi im Dutzendbereich liegt und nicht im Hunderterbereich.

  • Geschätzte Dauer:Modi werden nicht regelmäßig gesendet. Stattdessen sind Modi ereignisgesteuert und werden durch bestimmte Aktionen ausgelöst, z. B. durch das Öffnen einer Tür, das Einleiten einer Parksequenz, das Starten eines Ladezyklus und andere ähnliche Ereignisse, die vom OEM definiert werden.

Das benutzerdefinierte Modusdesign bietet die Flexibilität, bestimmte Modi zu definieren und zu verwalten, während der Orchestrator unabhängig von der zugrunde liegenden Zustandsautomatenlogik bleibt.

Unterstützte Modi

Damit Dienst-Bundles nur in benutzerdefinierten Modi veröffentlicht werden, die ihnen gehören, muss jedes Bundle die Liste der benutzerdefinierten Modi, die ihm gehören, explizit in seiner Orchestrator-Konfiguration deklarieren. Diese ist in der lokalen VM mit der Dienst-Bundle-Registrierung verfügbar. Versuche, in einem nicht deklarierten benutzerdefinierten Modus zu veröffentlichen, werden verworfen.

Um die benutzerdefinierten Modi zu deklarieren, die ein Dienstpaket veröffentlichen darf (und somit besitzt), wird das service_bundle_config-Protoschema um Folgendes erweitert:

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

Pakete basierend auf Modi konfigurieren

Die vorhandene Orchestrator-Proto-Konfiguration (die Condition-Komponente) unterstützt die Bearbeitung von Service-Bundles basierend auf benutzerdefinierten Modi:

message Condition {
  oneof root {
    string power_state = 1;
    string vehicle_state = 2;
    CustomState custom_state = 3;
    Condition not = 4;
    Expression and = 5;
    Expression or = 6;
  }
}

message CustomState {
  // Custom mode being checked.
  string mode = 1;
  // State of the custom mode.
  string state = 2;
}

Proto-Beispiel

Im folgenden Beispiel wird gezeigt, wie Instanzen eines Dienst-Bundles konfiguriert werden, die auf Grundlage eines TURN- und FOG-Status gestartet werden:

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

}

Neue benutzerdefinierte Modi festlegen

Das Festlegen eines neuen benutzerdefinierten Moduswerts beginnt mit dem Service-Bundle, das den gewünschten Wert an den lokalen Orchestrator auf derselben VM übermittelt. Der Orchestrator prüft dann, ob das Dienstpaket die Berechtigungen hat, die für die Veröffentlichung im angegebenen benutzerdefinierten Modus erforderlich sind. Dazu wird die in der .textproto definierte Konfiguration herangezogen, um festzustellen, ob der Wert an andere VMs weitergegeben werden soll. Nach der Weitergabe prüft jeder Orchestrator seine Konfiguration, um die Liste der Dienstbündel zu finden, für die der Status geändert werden soll.

RPC

Jeder Orchestrator, der auf jeder VM ausgeführt wird, erstellt einen RPC-Server, um auf neue benutzerdefinierte Moduswerte zu warten. Für jedes Dienstbündel, das einen benutzerdefinierten Modus aktualisieren möchte, muss ein RPC-Client für den Server erstellt werden. ACLs werden erzwungen, um zu verhindern, dass nicht autorisierte Bundles eine Verbindung zum Server herstellen.

Die Proto-Definition zum Festlegen eines neuen Werts über RPC sieht so aus:

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) {};
}

Stornierung von Stromübergängen

Der Orchestrator ermöglicht das Abbrechen laufender Energieübergänge über den SHUTDOWN_CANCELLED-Energiemodus (der vom VPM an den Orchestrator gesendet wird).

Betrachten Sie die folgende Orchestrator-Konfiguration als Beispiel:

state {
    condition {
        power_state: "SUSPEND_TO_RAM_ENTER"
    }
    instances_states {
        started: "instance-1"
        started: "instance-2"
        started: "instance-3"
    }
}

Wenn ein SHUTDOWN_CANCELLED-Modus empfangen wird, hängt das Verhalten des Orchestrators von zwei primären Szenarien ab. In beiden Fällen wird der SHUTDOWN_CANCELLED-Energiemodus an das Ende der Warteschlange angehängt. SHUTDOWN_CANCELLED wird dann ausgeführt, nachdem die Elemente in der Warteschlange verarbeitet wurden.

Szenario 1: Der aktuelle Modus ist ein Energiesparmodus

Wenn der Orchestrator ein Update des Energiemodus ausführt, wird eine Abbrechen-Anfrage für den laufenden Modus gesendet. Der Lifecycle Manager unterstützt das Abbrechen einer laufenden Umstellung nicht direkt, der Orchestrator prüft jedoch, dass keine neuen Service-Bundle-Anfragen initiiert werden.

Beispiel: Wenn instance-1 aus der Konfiguration im vorherigen Beispiel gerade gestartet wird, wenn der Modus SHUTDOWN_CANCELLED empfangen wird, wird der Start von instance-1 abgeschlossen. instance-2 und instance-3 werden jedoch nicht in den Status „Gestartet“ überführt.

Szenario 2: Ein Energiemodus ist in der Verarbeitungswarteschlange vorhanden

Wenn der Orchestrator eine Aktualisierung des Nicht-Stromsparmodus verarbeitet und sich in der Warteschlange der auszuführenden Modi eine Stromanfrage befindet, wird der Stromübergang aus der Warteschlange entfernt. Dadurch wird die Ausführung verhindert.

Beispiel: Wenn der Orchestrator mit der Konfiguration aus dem vorherigen Beispiel an einem Update arbeitet, das nicht mit der Stromversorgung zusammenhängt (z. B. einem Fahrzeug-Update), und SUSPEND_TO_RAM_ENTER in der Warteschlange steht, führt der Empfang von SHUTDOWN_CANCELLED dazu, dass keine der Instanzen (instance-1, instance-2, instance-3) gestartet wird.

Implementierungsbeispiel

Der Katalog für einen Client, der mit Middleware generierten Code verwenden möchte, um einen Client für den RPC-Server zu erstellen, kann so aussehen:

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

Wenn Sie Code generieren, müssen Sie die Abhängigkeit dem Orchestrator-Katalog hinzufügen:

--dependency-catalog-path orchestration/engine/stable/vsidl/*

Der Clientcode zum Senden eines neuen Werts sieht so aus:

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

Tools zur Fehlerbehebung

Der Orchestrator-Agent unterstützt das dumpsys-Tool. Sie können es aufrufen, indem Sie den folgenden Befehl für eine laufende SDV-Instanz ausführen:

adb shell dumpsys com.google.sdv.ISdvAgent/orch

Mit diesem Tool können Sie den internen Status des Orchestrator-Agents debuggen und analysieren. Dadurch wird Folgendes angezeigt:

  • Aktueller Modusstatus:Hier sehen Sie die aktiven Fahrzeug-, Energie- und benutzerdefinierten Modi.
  • Verlage und Webpublisher im benutzerdefinierten Modus:Hier wird angegeben, welche Dienste benutzerdefinierte Modi veröffentlichen können und für welche Modi.
  • Erforderlicher Status pro Dienst:Hier erfahren Sie den Status der einzelnen Dienstpakete basierend auf vordefinierten Bedingungen und aktuellen Modi. So lässt sich herausfinden, warum sich ein Dienst möglicherweise nicht im erwarteten Status befindet.
  • Status der Erzwingung des Modus:Hier erhalten Sie einen klaren Überblick über einen laufenden erzwungenen Modus oder den letzten erzwungenen Modus, falls keiner läuft.
  • Warteschlange für die Erzwingung von Modi:Hier sehen Sie Modi, die erzwungen werden sollen.

Beispiel:

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: []
----------------

Weitere Informationen zu einzelnen Dienst-Bundles, die vom Orchestrator verwaltet werden, erhalten Sie mit dem vorhandenen dumpsys aus dem Lifecycle Manager:

dumpsys google.sdv.lifecycle.ILifecycleManager/default

So erhalten Sie detaillierte Informationen zum Lebenszyklusstatus der einzelnen Dienste. Wenn Sie die Orchestrator-dumpsys-Ausgabe mit der Ausgabe von Lifecycle Manager kombinieren, erhalten Sie ein vollständiges Bild des Lebenszyklus der Service-Bundles in der VM.