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

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

  1. ГОТОВО: Обновление не выполняется.
  2. ПОДГОТОВКА: Диспетчер обновлений записывает обновление на диск, но не активирует его.
  3. АКТИВАЦИЯ: Диспетчер обновлений активирует подготовленное обновление, чтобы оно вступило в силу после перезагрузки.
  4. COMMIT: Менеджер обновлений делает обновление постоянным.

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

Рисунок 1. Основные принципы работы менеджера обновлений.

Диспетчер обновлений поддерживает обновления системы и обновления пакетов служб, которые описаны на этой странице.

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

Операционная система Android использует два набора разделов, называемых слотами , при этом одновременно активен только один слот. Обновление системы записывает новый набор разделов в неактивный слот, и система переключает активный слот при следующей перезагрузке. Для получения дополнительной информации о создании обновлений системы см. раздел A/B-обновления системы .

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

В AAOS SDV пакеты служб объединяют службы в рамках APEX-файлов. Обновления пакетов служб подготавливают новые APEX-файлы во временных сессиях. Система активирует эти обновленные пакеты после перезагрузки системы. Для получения дополнительной информации о создании APEX-файлов с пакетами служб см. раздел «Обновления пакетов служб» .

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

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

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

Рисунок 2. Конечный автомат менеджера обновлений.

API

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

Безопасность и доступ

Система ограничивает доступ к API с помощью политик авторизации. Только авторизованный клиент может совершать вызовы к менеджеру обновлений.

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

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

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

  • Подписка: Клиенты подписываются на обновления статуса, вызывая метод 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 : Отображает текущий статус механизма обновления во время системных обновлений:

    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 описаны в разделе Prepare .

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 , которые требуют указания пути к образу обновления, распространяемому по беспроводной сети (OTA). Остальные параметры извлекаются из образа, но вы можете указать их, чтобы переопределить извлеченные значения.

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-модуля и монтирует образ APEX-модуля в файловую систему.

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

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

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

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

Откат

Запрос Rollback возвращает систему в состояние, предшествующее обновлению.

rpc Rollback(RollbackRequest) returns (RollbackResponse) {}

message RollbackRequest {}

message RollbackResponse {}

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

Укажите, когда был произведен откат. Переход к новому государству Системные действия
(Только для обновления системы) PREPARE , PREPARE_SUSPEND_COMPLETEPREPARE_CANCELPREPARE_ROLLBACKREADY Обновление системы: Отменяет обновление системы.
PREPARE_FAILURE , PREPARE_COMPLETEPREPARE_ROLLBACKREADY Обновление системы: Отменяет обновление системы.

Обновление пакета служб: прерывает предварительно подготовленную сессию APEX.
ACTIVATE_PRE_REBOOT_COMPLETE , ACTIVATE_PRE_REBOOT_FAILUREACTIVATE_PRE_REBOOT_ROLLBACKREADY Отключает контрольную точку пользовательских данных.

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

Обновление пакета сервисов: удаляет предварительно настроенный APEX.
ACTIVATE_POST_REBOOT_COMPLETEACTIVATE_POST_REBOOT_ROLLBACKACTIVATE_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 {}