Update Manager

Update Manager esegue gli aggiornamenti per la sua VM. Update Manager si coordina con il client, fornito dall'integratore di sistemi. Il client fornisce il payload di aggiornamento e coordina l'aggiornamento complessivo del veicolo. L'aggiornamento è composto dai seguenti passaggi:

  1. READY:nessun aggiornamento in corso.
  2. PREPARE:Update Manager scrive l'aggiornamento sul disco, ma non lo rende attivo.
  3. ACTIVATE:Update Manager rende attivo l'aggiornamento preparato in modo che diventi effettivo dopo un riavvio.
  4. COMMIT:Update Manager rende permanente l'aggiornamento.

Una macchina a stati semplificata che illustra il flusso di lavoro di Update Manager

Figura 1. Funzionamento di alto livello di Update Manager.

Update Manager supporta gli aggiornamenti di sistema e gli aggiornamenti dei pacchetti di servizi, descritti in questa pagina.

Aggiornamenti di sistema

Il sistema operativo Android utilizza due set di partizioni chiamate slot, con un solo slot attivo alla volta. Un aggiornamento di sistema scrive un nuovo set di partizioni nello slot inattivo e il sistema cambia lo slot attivo al riavvio successivo. Per saperne di più sulla creazione di aggiornamenti di sistema, consulta Aggiornamenti di sistema A/B.

Aggiornamenti dei pacchetti di servizi

In AAOS SDV, i pacchetti di servizi raggruppano i servizi all'interno degli APEX. Gli aggiornamenti dei pacchetti di servizi eseguono lo staging dei nuovi file APEX nelle sessioni temporanee. Il sistema attiva questi pacchetti aggiornati dopo un riavvio del sistema. Per saperne di più sulla creazione di APEX dei pacchetti di servizi, consulta Aggiornamenti dei pacchetti di servizi.

Macchina a stati

Le richieste del client e gli eventi dei servizi di sistema guidano la macchina a stati di Update Manager. Update Manager è progettato per essere resiliente, recuperando il suo stato e riprendendo la procedura di aggiornamento anche dopo riavvii o arresti anomali imprevisti.

Una macchina a stati che illustra il flusso di lavoro di Update Manager

Figura 2. Macchina a stati di Update Manager.

API

Update Manager fornisce un'API che guida la procedura di aggiornamento tramite la macchina a stati. L'API utilizza VSIDL, che supporta i client che risiedono in qualsiasi VM che supporta SDV Comms e fornisce una notifica di errore della richiesta.

Sicurezza e accesso

Il sistema limita l'accesso all'API utilizzando i criteri di autorizzazione. Solo il client autorizzato può effettuare chiamate a Update Manager.

Aggiornamenti di stato

Poiché le operazioni di aggiornamento possono richiedere molto tempo, Update Manager fornisce aggiornamenti di stato asincroni. I client devono monitorare lo stato sottoscrivendo gli aggiornamenti di stato.

Gestione degli abbonamenti

  • Iscrizione:i client si abbonano agli aggiornamenti di stato chiamando il metodo SubscribeToStatusUpdates():

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

    Prima di chiamare SubscribeToStatusUpdates(), il client deve avviare un'interfaccia RPC che implementa UpdateManagerListenerService.

  • Annullamento dell'iscrizione:i client possono interrompere la ricezione degli aggiornamenti di stato chiamando UnsubscribeFromStatusUpdates():

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

UpdateManagerListenerService

I client che chiamano SubscribeToStatusUpdates() su UpdateManagerService devono implementare il seguente servizio per ricevere gli aggiornamenti di stato:

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 invia uno dei due messaggi possibili utilizzando il campo status_update:

  1. UpdateManagerStatus: inviato quando lo stato di Update Manager cambia.
  2. UpdateProgress: inviato per indicare l'avanzamento dell'aggiornamento durante gli stati PREPARE e ACTIVATE_PRE_REBOOT, poiché la procedura può richiedere molto tempo.

Stato e messaggi di errore

I messaggi di stato includono dettagli sullo stato e su eventuali errori:

  • UpdateManagerStatus:segnala la fase corrente dell'aggiornamento e qualsiasi motivo di errore:

    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: segnala lo stato attuale di Update Engine durante gli aggiornamenti di 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;
    }
    
    

Ottenere lo stato immediato

Puoi recuperare lo stato e il payload attuali in qualsiasi momento chiamando GetStatus(). I messaggi SystemUpdatePayload e ServiceBundleUpdatePayload sono descritti in Preparazione.

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

Preparazione

La richiesta Prepare avvia la procedura di aggiornamento eseguendo lo staging del payload, ma il sistema attende l'attivazione dell'aggiornamento:

rpc Prepare(PrepareRequest) returns (PrepareResponse) {}

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

message PrepareResponse {}

Se la richiesta è valida, lo stato passa a PREPARE e Update Manager avvia l'aggiornamento.

Il tipo di payload determina il tipo di aggiornamento.

Payload di aggiornamento di sistema

Un aggiornamento di sistema utilizza i dati SystemUpdatePayload, che richiedono un percorso a un'immagine di aggiornamento OTA (over-the-air). Gli altri parametri vengono analizzati dall'immagine, ma puoi specificarli per sostituire i valori analizzati.

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

Update Manager elabora l'immagine OTA (fornita dal client nella directory /data/ota_package) per eseguire i passaggi post-installazione, ma non cambia lo slot di avvio attivo. Quindi passa allo stato PREPARE_COMPLETE in caso di successo o allo stato PREPARE_FAILURE in caso di errore.

Sospensione dell'aggiornamento di sistema

Puoi mettere in pausa la procedura di aggiornamento solo per gli aggiornamenti di sistema. Questa richiesta è valida solo nello stato PREPARE.

  • Sospendi:mette in pausa l'aggiornamento, facendo passare lo stato a PREPARE_SUSPEND.

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

    In caso di successo, lo stato passa a PREPARE_SUSPEND_COMPLETE. In caso di errore, lo stato passa a PREPARE_FAILURE.

  • Riprendi:continua l'aggiornamento messo in pausa. Questa opzione è valida solo nello stato PREPARE_SUSPEND_COMPLETE.

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

    Lo stato torna allo stato PREPARE.

Payload di aggiornamento del pacchetto di servizi

Un aggiornamento del pacchetto di servizi utilizza ServiceBundleUpdatePayload, che contiene i percorsi ai file APEX e imposta il limite di tentativi di attivazione.

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

Update Manager verifica che i file APEX siano firmati correttamente ed esegue lo staging in una sessione. In caso di successo, lo stato passa a PREPARE_COMPLETE. In caso di errore, lo stato passa a PREPARE_FAILURE.

Attiva

La richiesta Activate attiva l'aggiornamento preparato al riavvio successivo.

rpc Activate(ActivateRequest) returns (ActivateResponse) {}

message ActivateRequest {}

message ActivateResponse {}

Pre-riavvio

Update Manager passa allo stato ACTIVATE_PRE_REBOOT durante l'attivazione dell'aggiornamento. Update Manager crea anche un checkpoint dei dati utente che diventa effettivo al riavvio del sistema.

Le azioni di attivazione variano in base al tipo di aggiornamento:

  • Aggiornamento di sistema:il sistema esegue i passaggi post-installazione e imposta lo slot di avvio per il passaggio al riavvio successivo.
  • Aggiornamento del pacchetto di servizi:il sistema contrassegna la sessione APEX di cui è stato eseguito lo staging come pronta per l'attivazione.

Se il sistema attiva l'aggiornamento, lo stato passa a ACTIVATE_PRE_REBOOT_COMPLETE, a indicare che la VM è pronta per il riavvio. In caso contrario, lo stato passa a ACTIVATE_PRE_REBOOT_FAILURE.

Post-riavvio

Dopo il riavvio, il sistema si avvia in modalità checkpoint. In questa modalità, il sistema non esegue il commit di alcuna modifica alla partizione dei dati utente nell'archiviazione permanente. Se il sistema non esegue il commit dell'aggiornamento, ripristina lo stato iniziale.

Limite di avvio

Il sistema ripristina le modifiche alla partizione dei dati utente in una delle seguenti condizioni:

  • Il client invia una richiesta Rollback() esplicita e riavvia il sistema.
  • Il sistema si avvia troppe volte senza che il client chiami Commit() o Rollback(). Il limite di avvio varia in base al tipo di aggiornamento:
    • Aggiornamento di sistema:l'implementazione di BootControl imposta questo limite. Ad esempio, il limite predefinito nell'implementazione utilizzata dai dispositivi Cuttlefish è di sette avvii.
    • Aggiornamento del pacchetto di servizi:il campo boot_attempts di ServiceBundleUpdatePayload fornito dal client imposta questo limite quando viene effettuata la richiesta Prepare().
Verifica

Il sistema verifica l'aggiornamento:

  • Aggiornamento di sistema:dm-verity controlla se lo slot aggiornato è danneggiato.
  • Aggiornamento del pacchetto di servizi:apexd controlla la firma di ogni APEX e monta l'immagine dell'APEX nel file system.

Se la verifica va a buon fine, lo stato passa a ACTIVATE_POST_REBOOT_COMPLETE. Update Manager attende Commit() o Rollback().

Se la verifica non va a buon fine, il sistema si riavvia. Quando il sistema raggiunge il limite di avvio, torna allo stato originale:

  • Aggiornamento di sistema:il sistema torna allo slot originale.
  • Aggiornamento del pacchetto di servizi:gli APEX aggiornati vengono eliminati e gli APEX originali vengono riattivati.

Se la verifica non va a buon fine per qualsiasi tipo di aggiornamento, lo stato passa a ACTIVATE_PRE_REBOOT_FAILURE dopo il ripristino dello stato originale.

Esegui il rollback

La richiesta Rollback avvia il ripristino dello stato del sistema precedente all'aggiornamento.

rpc Rollback(RollbackRequest) returns (RollbackResponse) {}

message RollbackRequest {}

message RollbackResponse {}

Puoi effettuare la richiesta Rollback() in molti stati. A seconda dello stato iniziale, il sistema esegue azioni diverse e seguono stati diversi:

Stato quando viene emesso il rollback Transizione di stato Azione di sistema
(Solo aggiornamento di sistema) PREPARE, PREPARE_SUSPEND_COMPLETE &rightarrow; PREPARE_CANCEL &rightarrow; PREPARE_ROLLBACK &rightarrow; READY Aggiornamento di sistema:annulla l'aggiornamento di sistema.
PREPARE_FAILURE, PREPARE_COMPLETE &rightarrow; PREPARE_ROLLBACK &rightarrow; READY Aggiornamento di sistema:annulla l'aggiornamento di sistema.

Aggiornamento del pacchetto di servizi:interrompe la sessione APEX di cui è stato eseguito lo staging.
ACTIVATE_PRE_REBOOT_COMPLETE, ACTIVATE_PRE_REBOOT_FAILURE &rightarrow; ACTIVATE_PRE_REBOOT_ROLLBACK &rightarrow; READY Disattiva il checkpoint dei dati utente.

Aggiornamento di sistema: annulla il cambio dello slot di avvio.

Aggiornamento del pacchetto di servizi: rimuove l'APEX di cui è stato eseguito lo staging.
ACTIVATE_POST_REBOOT_COMPLETE &rightarrow; ACTIVATE_POST_REBOOT_ROLLBACK &rightarrow; ACTIVATE_POST_REBOOT_ROLLBACK_COMPLETE Disattiva il checkpoint dei dati utente.

Aggiornamento di sistema: ripristina lo slot di avvio.

Aggiornamento del pacchetto di servizi: ripristina le sessioni APEX attive.

Per rendere effettivo il rollback è necessario un riavvio finale, dopo il quale lo stato passa a READY.

Esegui il commit

Questa richiesta indica che l'aggiornamento è stato completato correttamente e applica tutte le modifiche in modo permanente.

rpc Commit(CommitRequest) returns (CommitResponse) {}

message CommitRequest {}

message CommitResponse {}

Lo stato passa a COMMIT durante l'esecuzione delle azioni di commit:

  • Aggiornamento di sistema:Update Manager contrassegna l'avvio come riuscito, il che impedisce il rollback futuro e seleziona questo slot negli avvii successivi.
  • Aggiornamento del pacchetto di servizi:Update Manager contrassegna la sessione APEX di cui è stato eseguito lo staging come riuscita, chiudendo la sessione di aggiornamento e rendendo i pacchetti attivi in modo permanente.

Dopo che il sistema ha eseguito il commit dell'aggiornamento, Update Manager esegue il commit del checkpoint dei dati utente. Il sistema esegue il commit di tutti i nuovi dati utente scritti durante questo avvio nell'archiviazione permanente. Update Manager torna a READY, a indicare che l'aggiornamento è stato completato.

Disinstalla APEX

La richiesta UninstallApex rimuove la versione /data dei pacchetti di servizi. Puoi chiamare UninstallApex in qualsiasi stato, ma la VM deve essere riavviata affinché la disinstallazione diventi effettiva. Pertanto, evita di chiamare UninstallApex mentre è in corso un aggiornamento. UninstallApex non rimuove gli APEX preinstallati, non cancella i dati APEX e non rimuove le versioni APEX inattive.

rpc UninstallApex(UninstallApexRequest) returns (UninstallApexResponse) {}

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

message UninstallApexResponse {}