Update Manager

Der Update Manager führt Updates für seine VM aus. Er kommuniziert mit dem Client, der vom Systemintegrator bereitgestellt wird. Der Client stellt die Update-Nutzlast bereit und koordiniert das gesamte Fahrzeugupdate. Das Update besteht aus den folgenden Schritten:

  1. READY (BEREIT): Es wird kein Update ausgeführt.
  2. PREPARE (VORBEREITEN): Der Update Manager schreibt das Update auf die Festplatte, aktiviert es aber nicht.
  3. ACTIVATE (AKTIVIEREN): Der Update Manager aktiviert das vorbereitete Update, sodass es nach einem Neustart wirksam wird.
  4. COMMIT (BESTÄTIGEN): Der Update Manager macht das Update dauerhaft.

Vereinfachtes Zustandsdiagramm zur Veranschaulichung des Workflows des Update-Managers

Abbildung 1 : Überblick über die Funktionsweise des Update Managers.

Der Update Manager unterstützt Systemupdates und Updates von Dienstpaketen, die auf dieser Seite beschrieben werden.

System updates

Das Android-Betriebssystem verwendet zwei Partitionssätze, sogenannte Slots. Es ist immer nur ein Slot aktiv. Bei einem Systemupdate wird ein neuer Partitionssatz in den inaktiven Slot geschrieben und das System wechselt beim nächsten Neustart den aktiven Slot. Weitere Informationen zum Erstellen von Systemupdates finden Sie unter A/B-Systemupdates.

Updates von Dienstpaketen

In AAOS SDV werden Dienstpakete in APEX-Dateien zusammengefasst. Bei Updates von Dienstpaketen werden neue APEX-Dateien in temporären Sitzungen bereitgestellt. Das System aktiviert diese aktualisierten Pakete nach einem Neustart. Weitere Informationen zum Erstellen von APEX-Dateien für Dienstpakete finden Sie unter Updates von Dienstpaketen.

Zustandsautomat

Anfragen vom Client und Ereignisse von Systemdiensten steuern den Zustandsautomaten des Update Managers. Der Update Manager ist so konzipiert, dass er seinen Zustand wiederherstellen und den Updatevorgang auch nach unerwarteten Neustarts oder Abstürzen fortsetzen kann.

Ein Zustandsautomat, der den Workflow des Update-Managers veranschaulicht

Abbildung 2 : Zustandsautomat des Update Managers.

API

Der Update Manager bietet eine API, die den Updatevorgang über den Zustandsautomaten steuert. Die API verwendet VSIDL, das Clients in jeder VM unterstützt, die SDV Comms unterstützt, und Benachrichtigungen über fehlgeschlagene Anfragen bereitstellt.

Sicherheit und Zugriff

Das System beschränkt den API-Zugriff mithilfe von Autorisierungsrichtlinien. Nur der autorisierte Client kann Aufrufe an den Update Manager senden.

Statusaktualisierungen

Da Updatevorgänge lange dauern können, bietet der Update Manager asynchrone Statusaktualisierungen. Clients müssen den Status beobachten, indem sie Statusaktualisierungen abonnieren.

Aboverwaltung

  • Abonnieren:Clients abonnieren Statusaktualisierungen, indem sie die Methode SubscribeToStatusUpdates() aufrufen:

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

    Vor dem Aufruf von SubscribeToStatusUpdates() muss der Client eine RPC Schnittstelle starten, die UpdateManagerListenerService implementiert.

  • Abmelden:Clients können den Empfang von Statusaktualisierungen beenden, indem sie UnsubscribeFromStatusUpdates() aufrufen:

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

UpdateManagerListenerService

Clients, die SubscribeToStatusUpdates() für UpdateManagerService aufrufen, müssen den folgenden Dienst implementieren, um Statusaktualisierungen zu erhalten:

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 liefert eine von zwei möglichen Nachrichten über das Feld status_update:

  1. UpdateManagerStatus: Wird gesendet, wenn sich der Status des Update Managers ändert.
  2. UpdateProgress: Wird gesendet, um den Fortschritt des Updates in den Status PREPARE und ACTIVATE_PRE_REBOOT anzugeben, da der Vorgang viel Zeit in Anspruch nehmen kann.

Status- und Fehlermeldungen

Die Statusmeldungen enthalten Details zum Status und zu Fehlern:

  • UpdateManagerStatus:Meldet die aktuelle Phase des Updates und den Grund für einen Fehler:

    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: Meldet den aktuellen Status von Update Engine während Systemupdates:

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

Sofortigen Status abrufen

Sie können den aktuellen Status und die aktuelle Nutzlast jederzeit mit GetStatus() abrufen. Die SystemUpdatePayload und ServiceBundleUpdatePayload Nachrichten werden unter Vorbereiten beschrieben.

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

Vorbereiten

Die Anfrage Prepare startet den Updatevorgang, indem die Nutzlast bereitgestellt wird. Das System wartet jedoch mit der Aktivierung des Updates:

rpc Prepare(PrepareRequest) returns (PrepareResponse) {}

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

message PrepareResponse {}

Wenn die Anfrage gültig ist, wechselt der Status zu PREPARE und der Update Manager startet das Update.

Der Typ der Nutzlast bestimmt den Update-Typ.

Nutzlast für Systemupdate

Bei einem Systemupdate werden die Daten SystemUpdatePayload verwendet, die einen Pfad zu einem OTA-Update-Image (Over-the-Air) erfordern. Die anderen Parameter werden aus dem Image geparst. Sie können sie jedoch angeben, um die geparsten Werte zu überschreiben.

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

Der Update Manager verarbeitet das OTA-Image (das vom Client im Verzeichnis /data/ota_package bereitgestellt wird), um Schritte nach der Installation auszuführen. Er wechselt jedoch nicht den aktiven Boot-Slot. Anschließend wechselt er bei Erfolg in den Status PREPARE_COMPLETE oder bei einem Fehler in den Status PREPARE_FAILURE.

Systemupdate aussetzen

Sie können den Updatevorgang nur für Systemupdates pausieren. Diese Anfrage ist nur gültig, wenn der Status PREPARE ist.

  • Suspend (Aussetzen): Pausiert das Update und wechselt den Status über PREPARE_SUSPEND.

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

    Bei Erfolg wechselt der Status zu PREPARE_SUSPEND_COMPLETE. Bei einem Fehler wechselt der Status zu PREPARE_FAILURE.

  • Resume (Fortsetzen): Setzt das pausierte Update fort. Dies ist nur im Status PREPARE_SUSPEND_COMPLETE gültig.

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

    Der Status wechselt zurück zu PREPARE.

Nutzlast für Update von Dienstpaketen

Bei einem Update von Dienstpaketen wird ServiceBundleUpdatePayload verwendet. Diese Nutzlast enthält die Pfade zu den APEX-Dateien und legt das Limit für Aktivierungsversuche fest.

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

Der Update Manager prüft, ob die APEX-Dateien korrekt signiert sind, und stellt sie in einer Sitzung bereit. Bei Erfolg wechselt der Status zu PREPARE_COMPLETE. Bei einem Fehler wechselt der Status zu PREPARE_FAILURE.

Aktivieren

Die Anfrage Activate aktiviert das vorbereitete Update beim nächsten Neustart.

rpc Activate(ActivateRequest) returns (ActivateResponse) {}

message ActivateRequest {}

message ActivateResponse {}

Vor dem Neustart

Der Update Manager wechselt in den Status ACTIVATE_PRE_REBOOT, während er das Update aktiviert. Außerdem erstellt er einen Prüfpunkt für Nutzerdaten, der beim Neustart des Systems wirksam wird.

Die Aktivierungsaktionen unterscheiden sich je nach Update-Typ:

  • Systemupdate:Das System führt Schritte nach der Installation aus und legt fest, dass der Boot-Slot beim nächsten Neustart gewechselt wird.
  • Update von Dienstpaketen:Das System markiert die bereitgestellte APEX-Sitzung als bereit zur Aktivierung.

Wenn das System das Update erfolgreich aktiviert, wechselt der Status zu ACTIVATE_PRE_REBOOT_COMPLETE. Dies zeigt an, dass die VM bereit für den Neustart ist. Andernfalls wechselt der Status zu ACTIVATE_PRE_REBOOT_FAILURE.

Nach Neustart

Nach dem Neustart wird das System im Prüfpunktmodus gestartet. In diesem Modus werden keine Änderungen an der Partition für Nutzerdaten im permanenten Speicher gespeichert. Wenn das System das Update nicht erfolgreich bestätigt, werden diese Änderungen auf den ursprünglichen Zustand zurückgesetzt.

Boot-Limit

Das System setzt die Änderungen an der Partition für Nutzerdaten unter einer der folgenden Bedingungen zurück:

  • Der Client sendet eine explizite Rollback()-Anfrage und startet das System neu.
  • Das System wird zu oft gestartet, ohne dass der Client Commit() oder Rollback() aufruft. Das Boot-Limit unterscheidet sich je nach Update-Typ:
    • Systemupdate:Dies wird durch die BootControl-Implementierung festgelegt. Das Standardlimit in der Implementierung, die von Cuttlefish Geräten verwendet wird, beträgt beispielsweise sieben Starts.
    • Update von Dienstpaketen:Dies wird durch das Feld boot_attempts der ServiceBundleUpdatePayload festgelegt, die vom Client bereitgestellt wird, wenn die Anfrage Prepare() gesendet wird.
Bestätigung

Das System überprüft dann das Update:

  • Systemupdate: dm-verity prüft den aktualisierten Slot auf Beschädigungen.
  • Update von Dienstpaketen:apexd prüft die Signatur jeder APEX-Datei und hängt das Image der APEX-Datei an das Dateisystem an.

Wenn die Bestätigung erfolgreich ist, wechselt der Status zu ACTIVATE_POST_REBOOT_COMPLETE. Der Update Manager wartet auf Commit() oder Rollback().

Wenn die Bestätigung fehlschlägt, wird das System neu gestartet. Wenn das System das Boot Limit erreicht, wird der ursprüngliche Zustand wiederhergestellt:

  • Systemupdate:Das System wechselt zurück zum ursprünglichen Slot.
  • Update von Dienstpaketen:Die aktualisierten APEX-Dateien werden verworfen und die ursprünglichen APEX-Dateien werden wieder aktiviert.

Wenn die Bestätigung für einen Update-Typ fehlschlägt, wechselt der Status zu ACTIVATE_PRE_REBOOT_FAILURE, nachdem der ursprüngliche Zustand wiederhergestellt wurde.

Rollback

Die Anfrage Rollback startet die Rückkehr des Systems zum Zustand vor dem Update.

rpc Rollback(RollbackRequest) returns (RollbackResponse) {}

message RollbackRequest {}

message RollbackResponse {}

Sie können die Anfrage Rollback() in vielen Status senden. Je nach Ausgangsstatus führt das System unterschiedliche Aktionen aus und es folgen unterschiedliche Status:

Status, wenn Rollback ausgeführt wird Statusübergang Systemaktion
(Nur Systemupdate) PREPARE, PREPARE_SUSPEND_COMPLETE &rightarrow; PREPARE_CANCEL &rightarrow; PREPARE_ROLLBACK &rightarrow; READY Systemupdate:Bricht das Systemupdate ab.
PREPARE_FAILURE, PREPARE_COMPLETE &rightarrow; PREPARE_ROLLBACK &rightarrow; READY Systemupdate: Bricht das Systemupdate ab.

Update von Dienstpaketen: Bricht die bereitgestellte APEX-Sitzung ab.
ACTIVATE_PRE_REBOOT_COMPLETE, ACTIVATE_PRE_REBOOT_FAILURE &rightarrow; ACTIVATE_PRE_REBOOT_ROLLBACK &rightarrow; READY Deaktiviert den Prüfpunkt für Nutzerdaten.

Systemupdate: Bricht den Wechsel des Boot-Slots ab.

Update von Dienstpaketen: Entfernt die bereitgestellte APEX-Datei.
ACTIVATE_POST_REBOOT_COMPLETE &rightarrow; ACTIVATE_POST_REBOOT_ROLLBACK &rightarrow; ACTIVATE_POST_REBOOT_ROLLBACK_COMPLETE Deaktiviert den Prüfpunkt für Nutzerdaten.

Systemupdate: Wechselt den Boot-Slot zurück.

Update von Dienstpaketen: Setzt die aktiven APEX-Sitzungen zurück.

Damit das Rollback wirksam wird, ist ein letzter Neustart erforderlich. Danach wechselt der Status zu READY.

Commit

Diese Anfrage zeigt an, dass das Update erfolgreich abgeschlossen wurde, und wendet alle Änderungen dauerhaft an.

rpc Commit(CommitRequest) returns (CommitResponse) {}

message CommitRequest {}

message CommitResponse {}

Der Status wechselt zu COMMIT, während die Commit-Aktionen ausgeführt werden:

  • Systemupdate:Der Update Manager markiert den Boot als erfolgreich. Dadurch wird ein zukünftiges Rollback verhindert und dieser Slot bei nachfolgenden Starts ausgewählt.
  • Update von Dienstpaketen:Der Update Manager markiert die bereitgestellte APEX-Sitzung als erfolgreich, schließt die Update-Sitzung und aktiviert die Pakete dauerhaft.

Nachdem das System das Update bestätigt hat, bestätigt der Update Manager den Prüfpunkt für Nutzerdaten. Das System speichert alle neuen Nutzerdaten, die während dieses Starts geschrieben wurden, im permanenten Speicher. Der Update Manager wechselt zurück zu READY, was anzeigt, dass das Update abgeschlossen ist.

APEX-Dateien deinstallieren

Die Anfrage UninstallApex entfernt die /data-Version von Dienstpaketen. Sie können UninstallApex in jedem Status aufrufen. Die VM muss jedoch neu gestartet werden, damit die Deinstallation wirksam wird. Rufen Sie UninstallApex daher nicht auf, während ein Update ausgeführt wird. UninstallApex entfernt keine vorinstallierten APEX-Dateien, löscht keine APEX-Daten und entfernt keine inaktiven APEX-Versionen.

rpc UninstallApex(UninstallApexRequest) returns (UninstallApexResponse) {}

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

message UninstallApexResponse {}