Менеджер обновлений

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

  1. READY – обновление не выполняется.
  2. PREPARE. Менеджер обновлений записывает обновление на диск, но не активирует его.
  3. Активация. Менеджер обновлений активирует подготовленное обновление, чтобы оно вступило в силу после перезагрузки.
  4. COMMIT. Менеджер обновлений делает обновление постоянным.

Упрощенная схема, иллюстрирующая рабочий процесс Менеджера обновлений

Рисунок 1. Общие сведения о работе Менеджера обновлений.

Менеджер обновлений поддерживает обновление системы и пакетов сервисов, описанных на этой странице.

Обновление системы

В ОС Android используется два набора разделов, которые называются слотами. В каждый момент времени активен только один слот. При обновлении системы новый набор разделов записывается в неактивный слот, а при следующей перезагрузке активный слот переключается. Подробнее о создании обновлений системы…

Обновления пакета услуг

В AAOS SDV пакеты сервисов объединяются в APEX. Обновления пакетов сервисов подготавливают новые файлы APEX во временных сеансах. Система активирует эти обновленные пакеты после перезагрузки. Подробнее о создании APEX-файлов для пакетов сервисов…

Конечный автомат

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

Конечный автомат, иллюстрирующий рабочий процесс Менеджера обновлений

Рисунок 2. Обновление конечного автомата Менеджера.

API

Менеджер обновлений предоставляет API, который управляет процессом обновления через конечный автомат. API использует VSIDL, который поддерживает клиентов, находящихся на любой виртуальной машине с поддержкой SDV Comms, и предоставляет уведомления о сбоях запросов.

Доступ и безопасность

Доступ к API ограничивается с помощью правил авторизации. Вызывать Update Manager может только авторизованный клиент.

новости;

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

Управление подписками

  • Подписка. Клиенты подписываются на обновления статуса, вызывая метод SubscribeToStatusUpdates():

    rpc SubscribeToStatusUpdates(SubscribeToStatusUpdatesRequest)
        returns (SubscribeToStatusUpdatesResponse) {}
    
    message SubscribeToStatusUpdatesRequest {}
    
    message SubscribeToStatusUpdatesResponse {}
    

    Перед вызовом SubscribeToStatusUpdates() клиент должен запустить интерфейс RPC, который реализует UpdateManagerListenerService.

  • Отмена подписки. Клиенты могут отказаться от получения уведомлений о статусе, позвонив по номеру UnsubscribeFromStatusUpdates().

    rpc UnsubscribeFromStatusUpdates(UnsubscribeFromStatusUpdatesRequest)
        returns (UnsubscribeFromStatusUpdatesResponse) {}
    
    message UnsubscribeFromStatusUpdatesRequest {}
    
    message UnsubscribeFromStatusUpdatesResponse {}
    

UpdateManagerListenerService

Клиенты, которые вызывают SubscribeToStatusUpdates() в UpdateManagerService, должны реализовать следующий сервис, чтобы получать обновления статуса:

service UpdateManagerListenerService {
  /* Called when there is a status update from the Update Manager. */
  rpc OnStatusUpdate(OnStatusUpdateRequest) returns (OnStatusUpdateResponse) {}
}

message OnStatusUpdateRequest {
  oneof status_update {
    UpdateManagerStatus update_manager_status = 1;
    UpdateProgress update_progress = 2;
  }
}

message OnStatusUpdateResponse {}

OnStatusUpdateRequest возвращает одно из двух возможных сообщений в поле status_update:

  1. UpdateManagerStatus – отправляется при изменении состояния Менеджера обновлений.
  2. UpdateProgress – отправляется, чтобы показать ход обновления в состояниях PREPARE и ACTIVATE_PRE_REBOOT, поскольку процесс может занять много времени.

Статус и сообщения об ошибках

Сообщения о статусе содержат подробные сведения о состоянии и ошибках:

  • UpdateManagerStatus – текущий этап обновления и причина сбоя (если он произошел):

    message UpdateManagerStatus {
      /* The current state of the update */
      UpdateState update_state = 1;
      /* The reason for the failure, if the update failed */
      FailureReason failure_reason = 2;
    }
    
    enum UpdateState {
      /* The Update Manager is ready to accept a new update. */
      READY = 0;
      /* An update is being prepared. */
      PREPARE = 1;
      /* The update failed during the prepare step. Roll back the update to start a
       *   new update. */
      PREPARE_FAILURE = 2;
      /* The update was prepared successfully. */
      PREPARE_COMPLETE = 3;
      /* A rollback has started from the prepare step. When complete, transitions
       *   to READY. */
      PREPARE_ROLLBACK = 4;
      /* The prepared update is being activated. */
      ACTIVATE_PRE_REBOOT = 5;
      /* The update failed during the activate step before the reboot. Roll back the
       *   update to start a new update. */
      ACTIVATE_PRE_REBOOT_FAILURE = 6;
      /* The update was activated successfully. Reboot to complete activation. */
      ACTIVATE_PRE_REBOOT_COMPLETE = 7;
      /* A rollback has started from the activate pre-reboot step. When complete,
       *   transitions to READY. */
      ACTIVATE_PRE_REBOOT_ROLLBACK = 8;
      /* An update was successfully activated after the reboot. The update needs to
       *   be committed or rolled back to be completed. */
      ACTIVATE_POST_REBOOT_COMPLETE = 9;
      /* A rollback has started from the activate post-reboot step. */
      ACTIVATE_POST_REBOOT_ROLLBACK = 10;
      /* The rollback was completed successfully. Reboot to complete the
       *   rollback. */
      ACTIVATE_POST_REBOOT_ROLLBACK_COMPLETE = 11;
      /* The update is being committed. When complete, transitions to READY */
      COMMIT = 12;
      /* The prepare request is being cancelled */
      PREPARE_CANCEL = 13;
      /* The system update has started suspending */
      PREPARE_SUSPEND = 14;
      /* The system update has finished suspending */
      PREPARE_SUSPEND_COMPLETE = 15;
    }
    
    message FailureReason {
      /* The original error that triggered the failure */
      ErrorCode error_code = 1;
      /* Binder error message for most ErrorCodes. */
      string error_message = 2;
    }
    
    enum ErrorCode {
      Unspecified = 0;
      /* Error from UpdateEngine service */
      UpdateEngineError = 1;
      // Error from the ApexService
      ApexServiceError = 2;
      // Error from the BootControlService
      BootControlServiceError = 3;
      // Error from the VoldService
      VoldServiceError = 4;
    }
    
  • UpdateProgress. Отчет о текущем статусе Update Engine во время обновления системы.

    message UpdateProgress {
      /* Matches the enum UpdateStatus from the UpdateEngine service. */
      int32 status_code = 1;
    
      /* A value ranging from 0.0 to 1.0, 1.0 representing the process is complete. */
      float percentage = 2;
    }
    
    

Получайте информацию о статусе сразу

Вы можете в любой момент получить текущее состояние и полезную нагрузку, вызвав GetStatus(). Сообщения SystemUpdatePayload и ServiceBundleUpdatePayload описаны в разделе Подготовка.

rpc GetStatus(GetStatusRequest) returns (GetStatusResponse) {}

message GetStatusRequest {}

message GetStatusResponse {
  /* The status of the Update Manager */
  UpdateManagerStatus update_manager_status = 1;
  /* The current update payload, if one has been set through the Prepare() request */
  oneof payload {
    SystemUpdatePayload system_update_payload = 2;
    ServiceBundleUpdatePayload service_bundle_update_payload = 3;
  }
}

Подготовка

Запрос Prepare запускает процесс обновления, подготавливая полезную нагрузку, но система ожидает активации обновления:

rpc Prepare(PrepareRequest) returns (PrepareResponse) {}

message PrepareRequest {
  oneof payload {
    SystemUpdatePayload system_update_payload = 1;
    ServiceBundleUpdatePayload service_bundle_update_payload = 2;
  }
}

message PrepareResponse {}

Если запрос действителен, состояние меняется на PREPARE, и Менеджер обновлений запускает обновление.

Тип полезной нагрузки определяет тип обновления.

Полезная нагрузка обновления системы

Для обновления системы используются данные SystemUpdatePayload, для которых требуется путь к образу беспроводного обновления. Другие параметры извлекаются из изображения, но вы можете указать их, чтобы переопределить извлеченные значения.

message SystemUpdatePayload {
  /* Absolute path to the update image (e.g., /updates/ota_update.zip) */
  string payload = 1;

  /* Offset (in bytes) into the payload where the payload binary starts. */
  optional int64 payload_offset = 2;

  /* The amount of data (in bytes) to read from "payload" as the update payload. */
  optional int64 payload_size = 3;

  /* The header key value pairs to apply with the payload. */
  map<string, string> header_key_value_pairs = 4;
}

Менеджер обновлений обрабатывает образ OTA (предоставленный клиентом в каталоге /data/ota_package), чтобы выполнить действия после установки, но не переключает активный загрузочный слот. Затем он переходит в состояние PREPARE_COMPLETE в случае успеха или в состояние PREPARE_FAILURE в случае неудачи.

Приостановка обновления системы

Приостановить можно только обновление системы. Этот запрос действителен, только если он находится в состоянии PREPARE.

  • Приостановить. Обновление приостанавливается, статус меняется на PREPARE_SUSPEND.

    rpc Suspend(SuspendRequest) returns (SuspendResponse) {}
    
    message SuspendRequest {}
    
    message SuspendResponse {}
    

    В случае успеха статус меняется на PREPARE_SUSPEND_COMPLETE. В случае сбоя статус меняется на PREPARE_FAILURE.

  • Продолжить. Возобновляет приостановленное обновление. Это допустимо только в состоянии PREPARE_SUSPEND_COMPLETE.

    rpc Resume(ResumeRequest) returns (ResumeResponse) {}
    
    message ResumeRequest {}
    
    message ResumeResponse {}
    

    Состояние возвращается к PREPARE.

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

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

message ServiceBundleUpdatePayload {
  /* Absolute path to an .apex file. Multiple .apex files can be included. */
  repeated string apex_path = 1;

  /* Number of boots to attempt activation before aborting. Must be > 0. */
  int32 boot_attempts = 2;
}

Менеджер обновлений проверяет, правильно ли подписаны файлы APEX, и подготавливает их в рамках сеанса. В случае успеха статус меняется на PREPARE_COMPLETE. В случае сбоя статус меняется на PREPARE_FAILURE.

Активировать

Запрос Activate активирует подготовленное обновление при следующей перезагрузке.

rpc Activate(ActivateRequest) returns (ActivateResponse) {}

message ActivateRequest {}

message ActivateResponse {}

Перед перезагрузкой

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

Действия по активации зависят от типа обновления:

  • Обновление системы. Система выполняет действия после установки и настраивает слот загрузки для переключения при следующей перезагрузке.
  • Обновление пакета сервисов. Система помечает подготовленный сеанс APEX как готовый к активации.

Если система успешно активирует обновление, статус изменится на ACTIVATE_PRE_REBOOT_COMPLETE. Это означает, что виртуальная машина готова к перезагрузке. В противном случае статус изменится на ACTIVATE_PRE_REBOOT_FAILURE.

Запуск после перезагрузки

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

Ограничение на загрузку

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

  • Клиент отправляет явный запрос Rollback() и перезагружает систему.
  • Система загружается слишком много раз без вызова клиентом Commit() или Rollback(). Лимит загрузок зависит от типа обновления:
    • Обновление системы. Задается реализацией BootControl. Например, в реализации, используемой устройствами Cuttlefish, по умолчанию установлено ограничение в семь загрузок.
    • Обновление пакета услуг. Поле boot_attempts объекта ServiceBundleUpdatePayload, предоставленное клиентом, задает это значение при выполнении запроса Prepare().
Проверка

Затем система проверяет обновление:

  • Обновление системы. dm-verity проверяет обновленный слот на наличие повреждений.
  • Обновление пакета сервисов. apexd проверяет подпись каждого APEX-файла и монтирует его образ в файловую систему.

Если проверка прошла успешно, статус меняется на ACTIVATE_POST_REBOOT_COMPLETE. Менеджер обновлений ожидает Commit() или Rollback().

Если проверка не удалась, система перезагружается. Когда система достигает предела загрузки, она возвращается в исходное состояние:

  • Обновление системы. Система возвращается к исходному слоту.
  • Обновление пакета сервисов. Обновленные APEX-файлы удаляются, а исходные активируются повторно.

Если проверка не удалась, то после восстановления исходного состояния устанавливается статус ACTIVATE_PRE_REBOOT_FAILURE.

Откат

Запрос Rollback запускает процесс возврата системы к состоянию до обновления.

rpc Rollback(RollbackRequest) returns (RollbackResponse) {}

message RollbackRequest {}

message RollbackResponse {}

Запрос Rollback() можно отправлять в разных состояниях. В зависимости от начального состояния система выполняет разные действия, и за ними следуют разные состояния:

Состояние при откате Переход между состояниями Системное действие
(Только обновление системы) PREPARE, PREPARE_SUSPEND_COMPLETE &rightarrow; PREPARE_CANCEL &rightarrow; PREPARE_ROLLBACK &rightarrow; READY Обновление системы. Отменяет обновление системы.
PREPARE_FAILURE, PREPARE_COMPLETE &rightarrow; PREPARE_ROLLBACK &rightarrow; READY Обновление системы. Отменяет обновление системы.

Обновление пакета сервисов. Прерывает поэтапный сеанс APEX.
ACTIVATE_PRE_REBOOT_COMPLETE, ACTIVATE_PRE_REBOOT_FAILURE &rightarrow; ACTIVATE_PRE_REBOOT_ROLLBACK &rightarrow; READY Отключает контрольную точку пользовательских данных.

Обновление системы. Отменяет переключение слота загрузки.

Обновление пакета сервисов. Удаляет подготовленный APEX.
ACTIVATE_POST_REBOOT_COMPLETE &rightarrow; ACTIVATE_POST_REBOOT_ROLLBACK &rightarrow; ACTIVATE_POST_REBOOT_ROLLBACK_COMPLETE Отключает контрольную точку пользовательских данных.

Обновление системы. Переключает слот загрузки обратно.

Обновление пакета сервисов. Отменяет активные сеансы APEX.

Чтобы изменения вступили в силу, требуется перезагрузка, после которой статус меняется на READY.

Фиксация

Этот запрос указывает, что обновление завершено успешно, и применяет все изменения на постоянной основе.

rpc Commit(CommitRequest) returns (CommitResponse) {}

message CommitRequest {}

message CommitResponse {}

При выполнении действий по фиксации состояние меняется на COMMIT:

  • Обновление системы. Менеджер обновлений помечает загрузку как успешную, что предотвращает откат в будущем и выбирает этот слот при последующих загрузках.
  • Обновление пакета сервисов. Менеджер обновлений помечает подготовленный сеанс APEX как успешный, закрывает сеанс обновления и делает пакеты постоянно активными.

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

Удаление APEX-файлов

Запрос UninstallApex удаляет версию /data пакетов сервисов. Вызвать UninstallApex можно в любом состоянии, но для удаления потребуется перезагрузить виртуальную машину. Поэтому не вызывайте UninstallApex во время обновления. Команда UninstallApex не удаляет предустановленные APEX-файлы, данные APEX и неактивные версии APEX.

rpc UninstallApex(UninstallApexRequest) returns (UninstallApexResponse) {}

message UninstallApexRequest {
  message ApexInfo {
    string module_name = 1;
    int64 version_code = 2;
  }
  repeated ApexInfo apexes = 1;
}

message UninstallApexResponse {}