Gerenciador de atualizações

O Update Manager realiza atualizações para a VM. O Update Manager coordena com o cliente, que é fornecido pelo integrador de sistemas. O cliente fornece o payload de atualização e coordena a atualização geral do veículo. A atualização consiste nestas etapas:

  1. PRONTO:nenhuma atualização está em andamento.
  2. PREPARAR:o Update Manager grava a atualização no disco, mas não a ativa.
  3. ATIVAR:o Gerenciador de atualizações ativa a atualização preparada para que ela entre em vigor após uma reinicialização.
  4. CONFIRMAR:o Gerenciador de atualizações torna a atualização permanente.

Uma máquina de estado simplificada que ilustra o fluxo de trabalho do Update Manager

Figura 1. Operação de alto nível do Update Manager.

O Gerenciador de atualizações oferece suporte a atualizações do sistema e do pacote de serviços, que são descritas nesta página.

Atualizações do sistema

O SO Android usa dois conjuntos de partições chamados de slots, com apenas um slot ativo por vez. Uma atualização do sistema grava um novo conjunto de partições no slot inativo, e o sistema troca o slot ativo na próxima reinicialização. Para mais informações sobre como criar atualizações do sistema, consulte Atualizações do sistema A/B.

Atualizações de pacotes de serviços

No AAOS SDV, os pacotes de serviços agrupam serviços em APEXes. As atualizações do pacote de serviços preparam novos arquivos APEX em sessões temporárias. O sistema ativa esses pacotes atualizados após uma reinicialização. Para mais informações sobre como criar APEXs de pacote de serviços, consulte Atualizações do pacote de serviços.

Máquina de estado

As solicitações do cliente e os eventos dos serviços do sistema impulsionam a máquina de estados do Update Manager. O Gerenciador de atualizações foi projetado para ser resiliente, recuperando o estado e retomando o processo de atualização mesmo após reinicializações ou falhas inesperadas.

Uma máquina de estado que ilustra o fluxo de trabalho do Update Manager

Figura 2. Máquina de estado do Update Manager.

API

O Update Manager fornece uma API que impulsiona o processo de atualização pela máquina de estados. A API usa VSIDL, que é compatível com clientes em qualquer VM que ofereça suporte a comunicações SDV e fornece notificação de falha na solicitação.

Segurança e acesso

O sistema restringe o acesso à API usando políticas de autorização. Somente o cliente autorizado pode fazer chamadas para o Gerenciador de atualizações.

atualizações de status

Como as operações de atualização podem ser de longa duração, o Gerenciador de atualizações fornece atualizações de status assíncronas. Os clientes precisam monitorar o estado inscrevendo-se nas atualizações de status.

Gerenciamento de assinatura

  • Inscrição:os clientes se inscrevem para receber atualizações de status chamando o método SubscribeToStatusUpdates():

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

    Antes de chamar SubscribeToStatusUpdates(), o cliente precisa iniciar uma interface RPC que implementa UpdateManagerListenerService.

  • Cancelamento da inscrição:os clientes podem parar de receber atualizações de status chamando UnsubscribeFromStatusUpdates():

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

UpdateManagerListenerService

Os clientes que chamam SubscribeToStatusUpdates() em UpdateManagerService precisam implementar o seguinte serviço para receber atualizações de status:

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

O OnStatusUpdateRequest entrega uma de duas mensagens possíveis usando o campo status_update:

  1. UpdateManagerStatus: enviado quando o estado do Gerenciador de atualizações muda.
  2. UpdateProgress: enviado para indicar o progresso da atualização durante os estados PREPARE e ACTIVATE_PRE_REBOOT, já que o processo pode levar um tempo significativo.

Status e mensagens de erro

As mensagens de status incluem detalhes sobre o estado e falhas:

  • UpdateManagerStatus:informa a fase atual da atualização e o motivo da falha:

    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:informa o status atual do Update Engine durante as atualizações do sistema:

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

Receber status imediato

Você pode recuperar o estado e a carga útil atuais a qualquer momento chamando GetStatus(). As mensagens SystemUpdatePayload e ServiceBundleUpdatePayload são descritas em Preparar.

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

Preparação

A solicitação Prepare inicia o processo de atualização ao preparar o payload, mas o sistema aguarda para ativar a atualização:

rpc Prepare(PrepareRequest) returns (PrepareResponse) {}

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

message PrepareResponse {}

Se a solicitação for válida, o estado vai mudar para PREPARE, e o Update Manager vai iniciar a atualização.

O tipo do payload determina o tipo de atualização.

Payload de atualização do sistema

Uma atualização do sistema usa os dados SystemUpdatePayload, que exigem um caminho para uma imagem de atualização over-the-air (OTA). Os outros parâmetros são analisados da imagem, mas você pode especificá-los para substituir os valores analisados.

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

O Update Manager processa a imagem OTA (fornecida pelo cliente no diretório /data/ota_package) para executar etapas pós-instalação, mas não troca o slot de inicialização ativo. Em seguida, ele passa para o estado PREPARE_COMPLETE em caso de sucesso ou para o estado PREPARE_FAILURE em caso de falha.

Suspensão da atualização do sistema

É possível pausar o processo de atualização apenas para atualizações do sistema. Essa solicitação é válida apenas quando está no estado PREPARE.

  • Suspender:pausa a atualização, fazendo a transição do estado por PREPARE_SUSPEND.

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

    Em caso de sucesso, o estado passa a ser PREPARE_SUSPEND_COMPLETE. Em caso de falha, o estado passa a ser PREPARE_FAILURE.

  • Retomar:continua a atualização pausada. Isso é válido apenas no estado PREPARE_SUSPEND_COMPLETE.

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

    O estado volta para PREPARE.

Payload de atualização do pacote de serviços

Uma atualização do pacote de serviços usa o ServiceBundleUpdatePayload, que contém os caminhos para os arquivos APEX e define o limite de tentativas de ativação.

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

O Gerenciador de atualizações verifica se os arquivos APEX estão assinados corretamente e os prepara em uma sessão. Em caso de sucesso, o estado passa a ser PREPARE_COMPLETE. Em caso de falha, o estado passa a ser PREPARE_FAILURE.

Ativar

A solicitação Activate ativa a atualização preparada na próxima reinicialização.

rpc Activate(ActivateRequest) returns (ActivateResponse) {}

message ActivateRequest {}

message ActivateResponse {}

Pré-reinicialização

O Update Manager faz a transição para o estado ACTIVATE_PRE_REBOOT ao ativar a atualização. O Gerenciador de atualizações também cria um ponto de verificação de dados do usuário que entra em vigor quando o sistema é reinicializado.

As ações de ativação variam de acordo com o tipo de atualização:

  • Atualização do sistema:o sistema executa etapas pós-instalação e define o slot de inicialização para ativar na próxima reinicialização.
  • Atualização do pacote de serviços:o sistema marca a sessão APEX em etapas como pronta para ativação.

Se o sistema ativar a atualização, o estado vai mudar para ACTIVATE_PRE_REBOOT_COMPLETE, o que indica que a VM está pronta para reinicialização. Caso contrário, o estado passa a ser ACTIVATE_PRE_REBOOT_FAILURE.

Pós reinicialização

Após a reinicialização, o sistema será iniciado no modo de checkpoint. Nesse modo, o sistema não confirma nenhuma mudança na partição de dados do usuário para o armazenamento permanente. Se o sistema não confirmar a atualização, ele vai reverter essas mudanças para o estado inicial.

Limite de inicialização

O sistema reverte as mudanças na partição de dados do usuário em uma destas condições:

  • O cliente envia uma solicitação Rollback() explícita e reinicia o sistema.
  • O sistema é inicializado muitas vezes sem que o cliente chame Commit() ou Rollback(). O limite de inicialização varia de acordo com o tipo de atualização:
    • Atualização do sistema:a implementação BootControl define isso. Por exemplo, o limite padrão na implementação usada por dispositivos Cuttlefish é de sete inicializações.
    • Atualização do pacote de serviços:o campo boot_attempts do ServiceBundleUpdatePayload fornecido pelo cliente define isso quando a solicitação Prepare() é feita.
Verificação

Em seguida, o sistema verifica a atualização:

  • Atualização do sistema:o dm-verity verifica se há corrupção no slot atualizado.
  • Atualização do pacote de serviços:o apexd verifica a assinatura de cada APEX e monta a imagem do APEX no sistema de arquivos.

Se a verificação for bem-sucedida, o estado vai mudar para ACTIVATE_POST_REBOOT_COMPLETE. O Update Manager aguarda Commit() ou Rollback().

Se a verificação falhar, o sistema será reinicializado. Quando o sistema atinge o limite de inicialização, ele volta ao estado original:

  • Atualização do sistema:o sistema volta ao slot original.
  • Atualização do pacote de serviços:os APEXes atualizados são descartados, e os APEXes originais são reativados.

Se a verificação falhar para qualquer tipo de atualização, o estado vai mudar para ACTIVATE_PRE_REBOOT_FAILURE depois que o estado original for restaurado.

Reversão

A solicitação Rollback começa a retornar o sistema ao estado anterior à atualização.

rpc Rollback(RollbackRequest) returns (RollbackResponse) {}

message RollbackRequest {}

message RollbackResponse {}

Você pode fazer a solicitação de Rollback() em vários estados. Dependendo do estado inicial, o sistema realiza ações diferentes, e estados diferentes são seguidos:

Estado quando a reversão é emitida Transição de estado Ação do sistema
(Somente atualização do sistema) PREPARE, PREPARE_SUSPEND_COMPLETE &rightarrow; PREPARE_CANCEL &rightarrow; PREPARE_ROLLBACK &rightarrow; READY Atualização do sistema:cancela a atualização do sistema.
PREPARE_FAILURE, PREPARE_COMPLETE &rightarrow; PREPARE_ROLLBACK &rightarrow; READY Atualização do sistema:cancela a atualização do sistema.

Atualização do pacote de serviços:interrompe a sessão APEX em etapas.
ACTIVATE_PRE_REBOOT_COMPLETE, ACTIVATE_PRE_REBOOT_FAILURE &rightarrow; ACTIVATE_PRE_REBOOT_ROLLBACK &rightarrow; READY Desativa o ponto de verificação de dados do usuário.

Atualização do sistema:cancela a troca de slot de inicialização.

Atualização do pacote de serviços:remove o APEX temporário.
ACTIVATE_POST_REBOOT_COMPLETE &rightarrow; ACTIVATE_POST_REBOOT_ROLLBACK &rightarrow; ACTIVATE_POST_REBOOT_ROLLBACK_COMPLETE Desativa o ponto de verificação de dados do usuário.

Atualização do sistema:troca o slot de inicialização de volta.

Atualização do pacote de serviços:reverte as sessões APEX ativas.

É necessário fazer uma reinicialização final para que a reversão entre em vigor. Depois disso, o estado passa para READY.

Confirmação

Essa solicitação indica que a atualização foi concluída e aplica todas as mudanças de forma permanente.

rpc Commit(CommitRequest) returns (CommitResponse) {}

message CommitRequest {}

message CommitResponse {}

O estado passa para COMMIT ao realizar as ações de commit:

  • Atualização do sistema:o Gerenciador de atualizações marca a inicialização como bem-sucedida, o que impede reversões futuras e seleciona esse slot nas inicializações subsequentes.
  • Atualização do pacote de serviços:o Gerenciador de atualizações marca a sessão APEX em etapas como concluída, encerrando a sessão de atualização e ativando os pacotes de forma permanente.

Depois que o sistema confirma a atualização, o Gerenciador de atualizações confirma o ponto de verificação dos dados do usuário. O sistema confirma todos os novos dados do usuário gravados durante essa inicialização no armazenamento permanente. O Gerenciador de atualizações volta para READY, indicando que a atualização foi concluída.

Desinstalar APEXs

A solicitação UninstallApex remove a versão /data dos pacotes de serviços. É possível chamar UninstallApex em qualquer estado, mas a VM precisa ser reinicializada para que a desinstalação entre em vigor. Portanto, evite chamar UninstallApex enquanto uma atualização estiver em andamento. O UninstallApex não remove APEXes pré-instalados, apaga dados do APEX nem remove versões inativas do APEX.

rpc UninstallApex(UninstallApexRequest) returns (UninstallApexResponse) {}

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

message UninstallApexResponse {}