Настройка оркестратора

Оркестратор — это локальный агент SDV, работающий на каждой виртуальной машине (ВМ) и предоставляющий механизм для управления созданием, запуском, остановкой или уничтожением пакетов служб. Это осуществляется посредством конфигурации оркестровки, в которой вы определяете набор правил, определяющих, когда и как выполняются действия с экземплярами пакетов служб. Эти правила основаны на режимах транспортного средства, питания и пользовательских режимах.

Настроить Orchestrator можно в конфигурационных APEX-файлах или с помощью конфигураций для каждой виртуальной машины . Эта распределенная система конфигурации позволяет независимо обновлять части каждого пакета услуг через реестр пакетов услуг, как показано здесь.

Диаграмма распределенной конфигурации оркестратора

Рисунок 1. Схема конфигурации оркестратора.

Конфигурации, не зависящие от конкретного автомобиля, не меняются в зависимости от производителя или модели автомобиля. Конфигурация остается одинаковой для всех автомобилей каждого производителя. Конфигурации, специфичные для конкретного автомобиля, могут отличаться на разных автомобилях разных производителей, хотя конфигурация может быть одинаковой для всех автомобилей, выпускаемых одним и тем же производителем.

Конфигурация APEX

Во время выполнения Orchestrator обращается к реестру пакетов служб, чтобы получить оркестровку SDV для каждого пакета служб, загружая и анализируя каждую конфигурацию. Для получения дополнительной информации см. раздел «Метаданные оркестровки» .

Конфигурация для каждой виртуальной машины

При запуске Orchestrator загружает и анализирует конфигурацию виртуальной машины (если она присутствует). Абсолютный путь к этому конфигурационному файлу указывается с помощью системных свойств persist.sdv.orchestrator_config_path и ro.boot.sdv.orchestrator_config_path .

Система определяет путь к файлу конфигурации виртуальной машины при загрузке на основе следующей иерархии:

  1. Система проверяет свойство persist.sdv.orchestrator_config_path . Если оно имеет значение, используется указанный путь. Это значение сохраняется после перезагрузки или устанавливается во время выполнения.

  2. Если persist.sdv.orchestrator_config_path пуст, система проверяет свойство ro.boot.sdv.orchestrator_config_path . Если свойство ro.boot.sdv имеет значение, этот путь копируется в свойство persist и используется для текущей загрузки и всех последующих загрузок (если он не переопределен).

persist.sdv.orchestrator_config_path

persist.sdv.orchestrator_config_path — это основное свойство, используемое агентом SDV Orchestrator для получения пути к своему конфигурационному файлу. Это постоянное свойство, то есть его значение сохраняется после перезагрузки устройства. Вы можете изменить значение во время выполнения, что полезно для тестирования или определенных сценариев (например, сквозных тестов).

Значение можно установить во время выполнения с помощью команды setprop , а также во время сборки с помощью файла makefile (с расширением .mk ) или файла скрипта ресурсов с расширением .rc .

Установите свойство во время выполнения.

Установка свойства во время выполнения полезна для тестирования или внесения временных изменений, поскольку значение сохраняется после перезагрузки:

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

Установите это свойство во время сборки.

Чтобы задать это свойство в конфигурации сборки вашего устройства, добавьте строку в файл makefile вашего продукта или платы. Это идеально подходит для установки значения по умолчанию для нового образа устройства.

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

Это свойство также можно задать в файле скрипта ресурсов:

# Add this line to an .rc file
on {$property}
    setprop persist.sdv.orchestrator_config_path {$path_to_file}.textproto

ro.boot.sdv.orchestrator_config_path

ro.boot.sdv.orchestrator_config_path является свойством только для чтения, используемым при загрузке системы для задания начального значения свойства persist.sdv.orchestrator_config_path . Если persist.sdv.orchestrator_config_path пусто при загрузке системы, значение ro.boot.sdv.orchestrator_config_path копируется в него. После установки persist.sdv.orchestrator_config_path не будет перезаписано этим свойством при последующих загрузках.

Вы можете установить параметр ro.boot.sdv.orchestrator_config_path с помощью файла bootconfig или командной строки ядра.

Формат файла

Определите конфигурацию оркестрации в формате .textproto (например, в виде структурированного текста), чтобы новые конфигурации могли загружаться во время выполнения.

Синтаксис конфигурации

В этом разделе описывается синтаксис конфигурации.

Пакеты услуг

Каждый пакет сервисов должен быть определен с помощью конфигурации пакета сервисов, которая идентифицирует пакет в Orchestrator и используется для управления жизненным циклом экземпляра пакета. Конфигурация пакета сервисов определяет:

  • InstanceToGroupMapping позволяет включать экземпляр пакета служб в группу для установления зависимостей между экземплярами одного и того же пакета служб.

  • InstancesStates определяет различные состояния для экземпляра пакета служб.

  • InstancesStateConfiguration определяет состояние (из InstancesStates ), в которое должен быть переведен экземпляр пакета служб, если условие оценивается как true .

  • ServiceBundleConfig содержит информацию о конкретном пакете служб и его экземплярах. Для данного пакета он содержит соответствующие InstanceToGroupMapping и InstancesStateConfiguration .

  • CustomModes определяет список пользовательских режимов, в которых разрешено публиковать пакет. CustomModes используется для предотвращения несанкционированного изменения значения пользовательского режима пакетом. Это поле является необязательным, поскольку пакет службы может не публиковать данные ни в одном пользовательском режиме. Для получения дополнительной информации см. раздел «Пользовательские режимы» .

Необходимая конфигурация пакета

Как минимум, конфигурация пакета предоставляет следующие атрибуты:

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

    instance: "instance_1"
    instance: "instance_n"
}

Данное объявление определяет n экземпляров пакета услуг с соответствующими полными квалифицированными кодами (FQIN):

vm_name.package_name.service_bundle_name.instance_1

vm_name.package_name.service_bundle_name.instance_n

Имя виртуальной машины явно не указывается в конфигурации. Поскольку конфигурация определяется для каждой виртуальной машины отдельно, имя виртуальной машины всегда совпадает с именем той виртуальной машины, на которую развернут файл конфигурации, и уже известно агенту оркестрации.

Настройка экземпляров

Объявление экземпляров пакетов служб не имеет никакого эффекта. Для выполнения оркестратором экземпляры должны быть сконфигурированы. Например, оркестратору необходимо сообщить, при каких условиях (или состоянии виртуальной машины или транспортного средства) должен работать экземпляр. Для конфигурации экземпляров состояния конфигурации следует определять следующим образом:

  • condition — это выражение, описывающее состояние виртуальной машины или транспортного средства, которое должно быть оценено.

  • instances_states — это набор состояний для каждого экземпляра, которые должны применяться, если условие оценивается как true .

Для получения более подробной информации см. Условия .

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

    instance: "adaptive_light"
    instance: "reserve_light"

    state {
        condition {
            power_state: "ON"
        }

        instances_states {
            started: "adaptive_light"
            created: "reserve_light"
        }
    }
}

Сопоставление экземпляра и группы

Вы также можете настраивать экземпляры служб, включая их в группы служб. На уровне конфигурации пакета служб вы можете добавлять экземпляры в группы. Затем вы можете настроить группы на уровне конфигурации виртуальной машины. Для получения дополнительной информации см. следующий раздел и раздел «Пакеты служб» .

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

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

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

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

Протосхема

Вот пример прототипа схемы:

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

Конфигурация на уровне виртуальной машины

Конфигурация виртуальной машины позволяет определять сопоставления групп и настраивать группы. Она используется для моделирования зависимостей между пакетами служб на уровне виртуальной машины, обеспечивая тем самым гибкость в изменении состояния нескольких пакетов служб одновременно. Все экземпляры группы приводятся в указанное состояние.

Оркестратор не гарантирует порядок выполнения изменений состояния. Оркестратор переводит каждый экземпляр в заданное состояние.

Группы объявляются неявно путем использования имени group в любом из разделов конфигурации. Например, сопоставление экземпляров с группами, сопоставление групп с группами и состояния конфигурации групп.

сопоставление групп

Группы могут содержать другие группы. Объявив, что group_1 содержит subgroup_2 , мы фактически добавляем все экземпляры сервиса из subgroup_2 в group_1 .

Например:

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

Настройте группу

Объявление группы не имеет эффекта. Для выполнения оркестратором группы должны быть настроены. Например, оркестратору необходимо указать, при каких условиях или состоянии виртуальной машины или транспортного средства должны запускаться группы.

Группы можно настраивать аналогично экземплярам служб, то есть с помощью состояний конфигурации. Единственное отличие заключается в использовании groups_states вместо instances_states в синтаксисе:

state {
    condition {
        power_state: "ON"
    }

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

Протосхема

Вот пример прото-схемы:

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

Состояния конфигурации

Состояния конфигурации (states) определяют, когда экземпляр или группа служб запускается, останавливается или уничтожается, и состоят из conditions , а также instances_states (конфигурация пакета) и groups_states (конфигурация виртуальной машины).

Условия

Условия позволяют модели задать логическое условие, при выполнении которого (если оно true ) применяется определенное состояние экземпляра. Условие обладает следующими характеристиками:

  • Произвольно сложное логическое выражение (сформированное с помощью выражений and или not »), основанное на поддерживаемых сигналах, таких как питание, транспортное средство и пользовательский режим.

  • (Необязательно) Состояние конфигурации без условия всегда активно, то есть оценивается как true

Состояния экземпляра и состояния группы

instances_states и groups_states обладают следующими характеристиками.

  • Укажите, какие состояния необходимы агенту оркестрации для применения к заданным экземплярам или группам, при условии, что состояние active

  • При применении состояния к группе, это состояние применяется к каждому экземпляру пакета служб в группе. Порядок приведения экземпляров в это состояние не применяется.

К числу поддерживаемых штатов относятся:

  • started после вызова Service::on_start .

  • created

    • после вызова Service::new , но до вызова Service::on_start .

      ИЛИ

    • после вызова Service::on_stop , но до вызова Service::drop .

  • destroyed после вызова Service::drop .

Набор правил

Состояние конфигурации может быть активным или неактивным в зависимости от условия. Одновременно может быть активно несколько состояний. Когда агент оркестрации получает сигнал обновления, перед изменением жизненного цикла пакетов служб оцениваются все состояния конфигурации. Состояния экземпляров служб оцениваются в соответствии со следующими правилами:

  • Когда ни одно из активных состояний не применяется к экземпляру сервиса, он уничтожается.

  • Если выполняется одно или несколько активных состояний, применяется следующий порядок приоритета:

    1. destroyed имеет абсолютный приоритет.
    2. started имеет приоритет перед created .

Протосхема

Вот пример прото-схемы:

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

Стратегия восстановления после сбоя и перезапуска

Оркестратор предоставляет надежный механизм для обработки сбоев пакетов сервисов и ошибок перехода между режимами жизненного цикла. Поскольку оркестратор имеет целостное представление о состояниях сервисов и управляет переходами между режимами, он является наиболее подходящим компонентом для выполнения стратегии перезапуска и повторных попыток. Менеджер жизненного цикла (LM) сообщает оркестратору о сбоях пакетов сервисов посредством уведомлений о завершении работы связывателя. Чтобы избежать ненужных обращений связывателя к LM, оркестратор кэширует последнее состояние каждого пакета (независимо от того, было ли оно успешным или нет) и не применяет переходы повторно, если последнее известное состояние совпадает с новым запрошенным.

Настройка повторной попытки

Стратегию перезапуска и повторных попыток для каждого экземпляра можно определить в конфигурации Orchestrator с помощью retry_mapping . Если max_retries не задан в конфигурации, значение по умолчанию берется из системного свойства ro.boot.sdv.orchestrator.recovery.max_retries . Если это свойство не задано, значение возвращается к 0.

  • max_retries : Определяет количество повторных попыток перехода, которые Orchestrator предпринимает после временного сбоя или уведомления о сбое пакета. Счетчик повторных попыток сбрасывается до значения max_retries после успешной операции или обработки нового режима. Если несколько сопоставлений нацелены на один и тот же экземпляр, приоритет имеет то, у которого больше значение max_retries .

Пример конфигурации

service_bundle_config {
  package_name: "oem.package"
  service_bundle_name: "OemApplication"
  instance: "fog_front_light"
  instance: "fog_rear_light"

  # Defines the restart configuration mapping for specific instances.
  retry_mapping {
    instance: "fog_front_light"
    instance: "fog_rear_light"
    retry_config {
      max_retries: 3
    }
  }
}

Поведение, способствующее восстановлению

Логика перезапуска и повторных попыток Orchestrator корректно обрабатывает несколько сценариев сбоев:

  • Сбой в обычном режиме работы : если пакет служб аварийно завершает работу во время выполнения, оркестратор применяет стратегию перезапуска и пытается вернуть пакет в последнее запрошенное состояние на основе оставшихся попыток повторного запуска.
  • Сбой во время перехода в другой режим : Если пакет завершился с ошибкой во время принудительного применения нового режима, запрос на перезапуск ставится в очередь и обрабатывается позже. После обработки запроса Orchestrator проверяет, какое было последнее состояние экземпляра, и применяет перезапуск только в том случае, если экземпляр не находится в последнем запрошенном состоянии (из последнего перехода в другой режим).
  • Новый режим во время восстановления : Если Orchestrator получает запрос на переход в новый режим во время перезапуска пакета (или если он находится в очереди на перезапуск экземпляров), он отменяет текущее восстановление. Переход в новый режим вступает в силу, и счетчик повторных попыток сбрасывается, чтобы разрешить новый набор попыток для нового целевого состояния.

Оркестратор различает различные типы ошибок, возвращаемые менеджером жизненного цикла, чтобы определить стратегию повторных попыток:

  • Временные ошибки ( SERVICE_NOT_FOUND , OPERATION_FAILED , INTERNAL_ERROR ): Оркестратор повторяет операцию без каких-либо специальных действий по очистке.
  • Постоянные ошибки ( VALUE_CORRUPTED , INVALID_ARGUMENT ): Оркестратор предполагает, что пакет сервиса может находиться в поврежденном состоянии, и пытается завершить работу экземпляра сервиса перед повторной попыткой операции, чтобы обеспечить корректный перезапуск.
  • Постоянные ошибки ( PERMISSION_DENIED ): операция не повторяется, и пакет считается находящимся в невосстановимом состоянии.

Если менеджер жизненного цикла выходит из строя, все процессы пакетов служб теряются. Поскольку фактическое состояние неизвестно, оркестратор аннулирует каждый экземпляр и применяет стратегию перезапуска с оставшимися попытками, чтобы вернуть каждый экземпляр в последнее запрошенное состояние.

Чтобы предотвратить бесконечные циклы восстановления для пакетов, которые неоднократно аварийно завершают работу или дают сбои, счетчик повторных попыток сбрасывается до значения max_retries только после успешного завершения операции жизненного цикла или при запросе на переход в новый режим. Если пакет исчерпал свои попытки повторного выполнения из-за последовательных сбоев (например, сбой перехода с последующим аварийным завершением работы), он не перезапускается до тех пор, пока счетчик повторных попыток не будет сброшен.

Государственная отчетность перед медицинским наблюдателем

Оркестратор предоставляет внутренний интерфейс привязки, к которому регистрируется Монитор состояния (HM), что позволяет ему получать непрерывные обновления о состоянии всех пакетов служб. Через этот интерфейс Оркестратор активно сообщает о следующем:

  • Состояние жизненного цикла: предполагаемое состояние экземпляра, основанное на текущей конфигурации и активных режимах (например, запущен, создан или уничтожен).
  • Состояние восстановления: статус достижения желаемого состояния жизненного цикла, указывающий, находится ли экземпляр в рабочем состоянии, пытается ли он восстановиться после сбоя или не удалось восстановиться после исчерпания всех попыток.

Эта информация предоставляется для всех экземпляров, включая те, которые не зарегистрировались для мониторинга состояния. HM использует эту информацию для реализации своих API, позволяющих сообщать о состоянии виртуальной машины. Подробнее можно узнать в разделе «Мониторинг состояния» .

Примеры

В этом разделе представлены примеры настройки состояний с помощью условий.

Образец базового сервиса
  • Не имеет никаких условий и поэтому всегда активен.
  • Запускает один экземпляр службы.
state {
  # Note: This state has no condition, hence its actions are valid throughout the lifetime of the program
  instances_states { started: "ServiceBundleName" }
}
Пример приложения для систем отопления, вентиляции и кондиционирования воздуха.
  • Условие: Активно, когда custom_state != occupancy.OCCUPANCY_EMPTY || custom_state == preheat.PREHEAT_ON .

  • Объявляет несколько экземпляров служб, связанных с системами отопления, вентиляции и кондиционирования воздуха, как started .

state {
  condition {
    or {
      # I.e. when the vehicle is occupied (for example, by _DRIVER / _NON_DRIVER / _PET)
      not {
        custom_state {
          mode: "occupancy"
          state: "OCCUPANCY_EMPTY"
        }
      }
      custom_state {
        mode: "preheat"
        state: "PREHEAT_ON"
      }
    }
  }

  # HVAC-related services
  instances_states {
    started: "HvacTemperatureCommand"
    started: "TempSensorDriverZone"
    started: "TempSensorPassengerZone"
    started: "RefrigerantLoop"
  }
}
Образец энергосбережения
  • Условие: Активно, когда custom_state == system_power.SYSTEM_POWER_LOW && custom_state == range_ext.RANGE_EXT_ON .

    Этот штат можно рассматривать как штат, ориентированный на энергосбережение.

  • Объявляет один экземпляр сервиса, связанного с системами отопления, вентиляции и кондиционирования воздуха, destroyed .

  • В этом примере, когда активны режимы SYSTEM_POWER_LOW и RANGE_EXT_ON , приложение HVAC работает без экземпляра службы RefrigerantLoop :

    state {
      condition {
        and {
          custom_state {
            mode: "system_power"
            state: "SYSTEM_POWER_LOW"
          }
          custom_state {
            mode: "range_ext"
            state: "RANGE_EXT_ON"
          }
        }
      }
    
      # Disable services with high power consumption
      instances_states { destroyed: "RefrigerantLoop" }
    }
    
Образец жизни на борту
  • Условие: Активно, если power_state == ON && vehicle_state == LIFE_ON_BOARD .

    Это состояние можно рассматривать как ситуацию, когда кто-то находится в машине, и машина включена .

  • Объявляет, что датчики температуры работают.

  • В целях безопасности, когда человек находится в автомобиле, контролируются такие параметры, как температура.

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

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

Примеры

В этом разделе представлены полные примеры, содержащие:

  • Прототип конфигурации на уровне пакета служб, представляющий пакет служб с двумя экземплярами, каждый из которых является частью группы.

  • Прототип конфигурации на уровне виртуальной машины, внедряющий логику взаимодействия с группами на основе режимов.

Конфигурация на уровне пакета услуг

# proto-file: //system/software_defined_vehicle/orchestration/distributed_config/src/protos/service_bundle_config.proto
# proto-message: ServiceBundleConfig

package_name: "oem.package"
service_bundle_name: "OemApplication"
instance: "fog_front_light"
instance: "fog_rear_light"
instance: "turn_signal_light"
custom_mode: "FOG"
custom_mode: "TURN"

group_mapping {
    group: "fog_light"
    instance: "fog_front_light"
    instance: "fog_rear_light"
}

group_mapping {
    group: "flasher_light"
    instance: "turn_signal_light"
}

state {
    condition {
        power_state: "ON"
    }

    instances_states {
        created: "turn_signal_light"
        destroyed: "fog_front_light"
        destroyed: "fog_rear_light"
    }
}

Конфигурация на уровне виртуальной машины

# proto-file: //system/software_defined_vehicle/orchestration/distributed_config/src/protos/vm_config.proto
# proto-message: VmConfig

group_mapping {
    group: "lights"
    subgroup: "fog_light"
    subgroup: "flasher_light"
}

state {
    condition {
        custom_state {
            mode: "FOG"
            state: "ON"
        }
    }
    groups_states {
        started: "fog_light"
    }
}

state {
    condition {
        custom_state {
            mode: "TURN"
            state: "RIGHT"
        }
    }
    groups_states {
        started: "flasher_light"
    }
}

state {
    condition {
        vehicle_state: "SUSPEND_TO_RAM_ENTER"
    }
    groups_states {
        created: "lights"
    }
}

Настройка параллельного управления пакетами

Системное свойство ro.boot.sdv.max_bundles_management_threads является ключевым параметром настройки для управления производительностью и потреблением ресурсов во время операций жизненного цикла пакетов служб. Оно определяет максимальный уровень параллелизма для транзакций пакетов служб и напрямую влияет на две основные службы:

  1. Механизм оркестровки: Эта служба считывает свойство, чтобы определить, сколько одновременных вызовов (например, startService , stopService ) оркестратор может выполнить к менеджеру жизненного цикла. Это крайне важно для производительности во время загрузки и переходов между режимами, когда множество пакетов могут одновременно менять свое состояние.

  2. Менеджер жизненного цикла: Эта служба использует значение свойства для расчета размера пула потоков Binder, который отвечает за обработку всех входящих запросов. Это гарантирует, что у LM достаточно потоков для обработки одновременных запросов от Orchestrator.

Если это свойство не задано, обе службы по умолчанию принимают значение 12 .

Метод конфигурации

Вы можете установить это свойство в файле BoardConfig.mk вашего устройства, добавив его в переменную BOARD_BOOTCONFIG . Это гарантирует, что значение будет применяться каждый раз при загрузке устройства.

BOARD_BOOTCONFIG += \
    androidboot.sdv.max_bundles_management_threads=8

Чтобы изменить значение для вашего устройства, внесите изменения в эту строку в соответствующем файле BoardConfig.mk и выполните пересборку.

Оптимизация во время загрузки

Свойство ro.sdv.orchestrator.state.ready — это логическое свойство write-once , являющееся частью стратегии оптимизации производительности во время загрузки. Оно указывает на то, что агент оркестровки завершил инициализацию и готов начать управление жизненным циклом пакетов служб. Его основная цель — определить приоритет запуска оркестратора и управляемых им пакетов служб путем управления последовательностью запуска других агентов SDV.

  • Задается: агентом оркестровки.
  • Когда: Один раз во время загрузки системы.
  • Использование: Это свойство используется системой инициализации для управления последовательностью запуска большинства агентов SDV (менеджер обновлений, поставщик VSIDL, монитор работоспособности, обнаружение служб, туннель данных, RPC, VPM и телеметрия). Запуская оркестратор на ранней стадии и заставляя другие агенты ожидать этого параметра, система гарантирует, что оркестратор сможет начать свою критически важную задачу запуска пакетов служб, не конкурируя за системные ресурсы.

Производительность

При загрузке системы одновременный запуск всех агентов может привести к конкуренции за ресурсы, замедляя общий процесс загрузки. Для решения этой проблемы используется последовательный порядок запуска, обеспечиваемый с помощью системных свойств:

  1. Реестр пакетов услуг: Запускается первым для загрузки всех метаданных пакетов услуг.
  2. Менеджер жизненного цикла и оркестратор: эти основные агенты запускаются, как только реестр будет готов. Такой ранний запуск имеет решающее значение, поскольку позволяет оркестратору начать оценку своей конфигурации и подготовиться к немедленному запуску пакетов служб.
  3. Другие агенты SDV: Запускайте только после того, как Orchestrator будет готов.

Такая контролируемая последовательность гарантирует, что оркестратор имеет приоритет в использовании системных ресурсов для запуска пакетов служб в самый ранний возможный момент, что приводит к более быстрой, детерминированной и эффективной загрузке системы.

Режимы, используемые оркестратором.

Агент оркестрации поддерживает активную подписку на режимы работы транспортного средства и энергопотребления, передаваемые системой управления транспортными средствами и энергопотреблением (VPM). При первоначальном установлении соединения между оркестратором и системой управления транспортными средствами и энергопотреблением (VPM) оркестратор устанавливает следующие логические системные свойства в значение true :

  • sdv.orchestrator.bootup.power_mode.ready

  • sdv.orchestrator.bootup.vehicle_mode.ready

Используя конфигурационный файл в качестве ориентира, агент оркестрации динамически вычисляет набор пакетов служб, которые должны находиться в рабочем состоянии, на основе текущих значений полученных режимов. Затем оркестратор взаимодействует с менеджером жизненного цикла, выдавая различные команды для приведения фактического состояния пакетов служб в соответствие с вычисленным целевым состоянием.

Состояния транспортного средства и мощности

Агент управления режимом работы и питанием транспортного средства (VPM) позволяет компонентам SDV получать информацию о текущем состоянии транспортного средства, например, о режиме работы (например, «Парковка» или «Движение») и состоянии питания (например, «Включено» и «Приостановка»). Orchestrator оценивает эти значения, чтобы определить, какие пакеты служб должны запускаться в соответствии с конфигурацией Orchestrator. Для получения дополнительной информации см. раздел «Управление транспортным средством и питанием» .

Пользовательские режимы

Учитывая их количество, мы не можем смоделировать все режимы работы автомобиля. У каждого производителя разные потребности, и стандартизация режимов работы автомобиля не может охватить все сценарии использования. В результате мы поддерживаем режимы, специфичные для каждого производителя, известные как пользовательские режимы . Эти режимы не расширяют существующие режимы работы автомобиля и режимы мощности. Вместо этого они предоставляют способ определения новых режимов.

Функциональность:

  • Глобальный охват: Пользовательские режимы являются глобальными и применяются единообразно ко всем виртуальным машинам, управляемым Orchestrator.

  • Структура: Каждое изменение пользовательского режима состоит из двух элементов:

    • Название: Уникальный идентификатор, выбранный производителем оборудования для обозначения пользовательского режима.

    • Значение: Текущее состояние пользовательского режима, которое может быть UNDEFINED если значение не задано.

  • Роль оркестратора: Оркестратор выступает в качестве пассивного приемника значений пользовательского режима.

  • Роль пакета сервиса: Каждый пакет сервиса может содержать несколько пользовательских режимов и публиковать новые значения в любой из них. Несколько пакетов сервисов могут содержать один и тот же пользовательский режим, что означает, что пользовательский режим может получать новые значения из разных источников.

  • Ответственность за проверку: производители оборудования несут ответственность за обеспечение корректных переходов состояний. Оркестратор принимает любое новое значение.

Предполагаемые характеристики:

  • Примерное количество: режимы питания и режимы работы транспортного средства управляют жизненным циклом большинства пакетов услуг, а пользовательские режимы играют вспомогательную роль. Мы ожидаем, что количество пользовательских режимов будет исчисляться десятками, а не сотнями.

  • Расчетное время срабатывания: Режимы не передаются периодически. Вместо этого, режимы запускаются событиями, срабатывающими при определенных действиях, таких как открытие двери, запуск последовательности парковки, начало цикла зарядки и другие подобные события, имеющие значение, определенное производителем.

Разработка пользовательских режимов обеспечивает гибкость в определении и управлении конкретными режимами, позволяя при этом Orchestrator оставаться независимым от базовой логики конечного автомата.

Поддерживаемые режимы

Чтобы гарантировать, что пакеты служб публикуются только в принадлежащие им пользовательские режимы, каждый из них должен явно указать список принадлежащих ему пользовательских режимов в своей конфигурации Orchestrator, которая доступна в локальной виртуальной машине вместе с реестром пакетов служб. Попытки публикации в неуказанный пользовательский режим будут отклонены.

Для объявления пользовательских режимов, которые разрешено публиковать (и, следовательно, которыми владеет) пакету служб, схема протокола service_bundle_config расширяется следующим образом:

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

Настройте пакеты в зависимости от режимов.

Существующая конфигурация протокола Orchestrator (компонент Condition ) поддерживает управление пакетами сервисов на основе пользовательских режимов:

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

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

Прототип образца

В следующем примере показано, как настроить запуск экземпляров пакета служб в зависимости от состояния TURN и FOG :

service_bundle_config {
package_name: "oem.package"
service_bundle_name: "OemApplication"
instance: "flasher_light"
// Service bundle is allowed to set values for the TURN mode
custom_mode: "TURN"
// Service bundle is allowed to set values for the FOG mode
custom_mode: "FOG"

state {
    condition {
        custom_state {
            mode: "TURN"
            state: "LEFT"
        }
    }
    instances_states {
        started: "flasher_light"
    }
}

state {
    condition {
        custom_state {
            mode: "FOG"
            state: "ON"
        }
    }
    // Group assumed to be defined containing all FOG lights instances.
    groups_states {
        started: "fog_lights"
    }
}

}

Установить новые пользовательские режимы

Процесс установки нового значения пользовательского режима начинается с пакета служб, который передает желаемое значение локальному оркестратору, работающему на той же виртуальной машине. Затем оркестратор проверяет, имеет ли пакет служб необходимые разрешения для публикации в указанном пользовательском режиме, используя конфигурацию, определенную в файле .textproto , чтобы определить, следует ли распространять значение на другие виртуальные машины. После распространения каждый оркестратор проверяет свою конфигурацию, чтобы найти список пакетов служб, для которых необходимо изменить состояние.

РПК

Каждый Orchestrator, работающий на каждой виртуальной машине, создает RPC-сервер для прослушивания новых значений пользовательского режима. Каждый пакет служб, желающий обновить пользовательский режим, должен создать RPC-клиент для подключения к серверу. Для предотвращения подключения неавторизованных пакетов к серверу используются списки контроля доступа (ACL).

Пример определения протокола для установки нового значения через RPC выглядит следующим образом:

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

Отмена переходов власти

Оркестратор позволяет отменять текущие переключения питания с помощью режима питания SHUTDOWN_CANCELLED (отправляемого VPM в Оркестратор).

Рассмотрим в качестве примера следующую конфигурацию Orchestrator:

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

При получении сигнала режима SHUTDOWN_CANCELLED поведение оркестратора определяется двумя основными сценариями. В обоих случаях сигнал режима SHUTDOWN_CANCELLED добавляется в конец очереди. Затем, после обработки элементов в очереди, выполняется SHUTDOWN_CANCELLED .

Сценарий 1: Текущий режим работы — режим энергосбережения.

Если Orchestrator выполняет обновление режима энергосбережения, запрашивается отмена текущего режима. Хотя Lifecycle Manager по своей сути не поддерживает отмену текущего перехода, Orchestrator проверяет, не инициированы ли новые запросы на пакеты служб.

Пример: Если instance-1 из конфигурации предыдущего примера находится в процессе запуска, когда получен сигнал SHUTDOWN_CANCELLED , запуск instance-1 завершается. Однако instance-2 и instance-3 не переходят в состояние запуска.

Сценарий 2: В очереди обработки присутствует режим энергосбережения.

В случае, если Orchestrator обрабатывает обновление режима, отличного от режима энергосбережения, и в очереди на выполнение находится запрос на изменение режима энергосбережения, переход на другой режим энергосбережения удаляется из очереди. Это предотвращает его выполнение.

Пример: Используя конфигурацию из предыдущего примера, если Orchestrator работает над обновлением, не связанным с питанием (например, обновлением транспортного средства), и SUSPEND_TO_RAM_ENTER находится в очереди, получение SHUTDOWN_CANCELLED приводит к тому, что ни один из экземпляров ( instance-1 , instance-2 , instance-3 ) не запускается.

Пример реализации

Каталог для клиента, который хочет использовать сгенерированный промежуточным ПО код для создания клиента к RPC-серверу, может выглядеть примерно так:

# proto-file: //system/software_defined_vehicle/vsidl/language/src/protos/sdv/vsidl/v1/syntax.proto
# proto-message: VsidlEntry

package: "package_name"

service_bundle {
    name: "service_bundle_name"

    client {
        service: "com.android.sdv.orchestrator.CustomStateService"
    }
}

При генерации кода необходимо добавить зависимость в каталог Orchestrator:

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

Код клиента для отправки нового значения выглядит следующим образом:

let fqin = ServiceFqin::builder()
        .sdv_vm_name("vm_name")
        .sdv_package_name("package_name")
        .service_bundle_name("service_bundle_name")
        .service_instance_name("instance_name")
        .build()
        .unwrap();
let context_ref = ContextRef::create(fqin);
let comms = Arc::new(SdvComms { context: context_ref });
// service_bundle_name is the bundle generated with middleware code that defines
// the RPC client to "com.android.sdv.orchestrator.CustomStateService".
let client = service_bundle_name::new(comms).await.unwrap();
let rpc_client = client
        .create_rpc_client::<Client>(
            UnitName::builder()
                .vm_name(comms.context.get_self_fqin().get_sdv_vm_name())
                .package_name("com.android.sdv.orchestrator")
                .bundle_name("OrchestratorServiceBundle")
                .service_unit_name(Client::DEFAULT_UNIT_NAME)
                .build()
                .unwrap(),
            ClientOptions::default(),
        )
        .await;
let client = Arc::new(rpc_client.unwrap());
let request = SetCustomStateRequest {
mode: custom_mode_name,
value: custom_mode_value,
timestamp: MessageField::some(Timestamp::now()),
..Default::default()
};
let result = client.SetCustomState(&request).await;
// Process result

инструменты отладки

Агент Orchestrator поддерживает инструмент dumpsys. Вы можете запустить его, выполнив следующую команду на работающем экземпляре SDV:

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

Используйте этот инструмент для отладки и получения информации о внутреннем состоянии агента Orchestrator. При этом отобразится следующее:

  • Текущее состояние режимов: Отображаются активные режимы автомобиля, питания и пользовательские режимы.
  • Издатели пользовательских режимов: Определите, какие сервисы могут публиковать пользовательские режимы (и для каких режимов).
  • Требуемое состояние для каждой службы: Изучение состояния каждого пакета служб на основе предопределенных условий и текущих режимов. Это помогает диагностировать причины, по которым служба может находиться не в ожидаемом состоянии.
  • Статус применения режима: Получите четкое представление о текущем применяемом режиме или о последнем применяемом режиме, если ни один из них не был применен в данный момент.
  • Очередь принудительного применения режимов: просмотр режимов, ожидающих применения.

Например:

AGENT NAME: SDV Agent dump - Orchestrator
AGENT FQIN: instance1:com.android.sdv.orchestrator.OrchestratorServiceBundle/default
AGENT STATE: See orchestrator state below.
----------------
----------------
INTERNAL STATE REPORTERS:

*NAME: Configuration state
*REPORT:
Active modes:
MODE                          VALUE                         TIMESTAMP (scs, ns)
Power                         POWER_OFF_EXIT                -
Vehicle                       VEHICLE_ON                    -
Custom("CHARGING")            ON                            1750757590 (scs) 466507459 (ns)
Custom("TIRE_PRESSURE")       front-left                    1750757570 (scs) 554522995 (ns)

Modes allowed to publish by bundle (FQIN: modes):
com.android.sdv.sample.orchestration/CustomModeControlBundle: CHARGING, TIRE_PRESSURE

Requested state for instances:
STATE          FQIN
Started        com.android.sdv.sample.orchestration/CustomModeControlBundle/always-started-instance
Started        com.android.sdv.sample.orchestration/OrchestratedServiceBundle/my-instance
Started        com.sdv.oem.sample.diagnostics/DiagnosticsSampleWithDataItem/instance
Started        com.sdv.oem.sample.diagnostics/DiagnosticsSampleWithEvent/instance
Started        com.sdv.oem.user_preferences/UserPreferencesServiceBundle/default
----------------
*NAME: Engine state
*REPORT:
Last mode enforced was Custom("CHARGING") with value "ON"

Next modes to process: []
----------------

Чтобы узнать больше об отдельных пакетах служб, управляемых Orchestrator, используйте существующий dumpsys из Lifecycle Manager следующим образом:

dumpsys google.sdv.lifecycle.ILifecycleManager/default

Это позволяет получить подробную информацию о состоянии жизненного цикла каждой службы. Объединение вывода команды orchestrator dumpsys с выводом Lifecycle Manager дает полную картину жизненного цикла пакетов служб в виртуальной машине.