アップデート マネージャー

Update Manager は、VM の更新を実行します。Update Manager は、システム インテグレータが提供するクライアントと連携します。クライアントは更新ペイロードを提供し、車両全体の更新を調整します。 更新は次の手順で行われます。

  1. READY: 更新は進行していません。
  2. PREPARE: Update Manager は更新をディスクに書き込みますが、有効にはしません。
  3. ACTIVATE: Update Manager は準備した更新を有効にし、再起動後に有効になるようにします。
  4. COMMIT: Update Manager は更新を永続的にします。

Update Manager のワークフローを示す簡略化されたステート マシン

図 1.Update Manager のハイレベルなオペレーション。

Update Manager は、このページで説明するシステム アップデートとサービス バンドル アップデートをサポートしています。

システム アップデート

Android OS は、スロットと呼ばれる 2 つのパーティション セットを使用します。一度にアクティブになるのは 1 つのスロット のみです。システム アップデートは、非アクティブ スロットに新しいパーティション セットを書き込み、次の再起動時にアクティブ スロットを切り替えます。システム アップデートのビルドの詳細については、A/B システム アップデートをご覧ください。

サービス バンドル アップデート

AAOS SDV では、サービス バンドルは APEX 内でサービスをパッケージ化します。サービス バンドル アップデートは、一時セッションで新しい APEX ファイルをステージングします。システムは、システムの再起動後にこれらの更新されたバンドルを有効にします。サービス バンドル APEX のビルドの詳細については、サービス バンドル アップデートをご覧ください。

ステートマシン

クライアントからのリクエストとシステム サービスからのイベントによって、Update Manager ステートマシンが駆動します。Update Manager は復元力が高く、予期しない再起動やクラッシュが発生した場合でも、状態を復元して更新プロセスを再開できます。

Update Manager のワークフローを示す状態マシン

図 2.Update Manager ステートマシン。

API

Update Manager は、ステートマシンを介して更新プロセスを駆動する API を提供します。この API は VSIDL を使用します。VSIDL は、SDV Comms をサポートする任意の VM に存在するクライアントをサポートし、リクエストの失敗通知を提供します。

セキュリティとアクセス

システムは、認可ポリシーを使用して API アクセスを制限します。認可されたクライアントのみが Update Manager を呼び出すことができます。

ステータスの更新

更新オペレーションは長時間実行される可能性があるため、Update Manager は非同期のステータス更新を提供します。クライアントは、ステータス更新を登録して状態をモニタリングする必要があります。

定期購入の管理

  • 登録: クライアントは、SubscribeToStatusUpdates() メソッドを呼び出してステータス更新を登録します。

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

    クライアントは、SubscribeToStatusUpdates() を呼び出す前に、UpdateManagerListenerService を実装する RPC インターフェースを開始する必要があります。

  • 登録解除: クライアントは、UnsubscribeFromStatusUpdates() を呼び出してステータス更新の受信を停止できます。

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

UpdateManagerListenerService

UpdateManagerServiceSubscribeToStatusUpdates() を呼び出すクライアントは、ステータス更新を受信するために次のサービスを実装する必要があります。

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: Update Manager の状態が変更されたときに送信されます。
  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 に移行し、Update Manager が更新を開始します。

ペイロードのタイプによって、更新タイプが決まります。

システム アップデートのペイロード

システム アップデートでは、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;
}

Update Manager は、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 状態に戻ります。

サービス バンドル アップデートのペイロード

サービス バンドル アップデートでは、APEX ファイルのパスが含まれ、有効化試行回数の上限が設定されている ServiceBundleUpdatePayload を使用します。

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 は、APEX ファイルが正しく署名されていることを確認し、セッションでステージングします。成功すると、状態は PREPARE_COMPLETE に移行します。失敗すると、状態は PREPARE_FAILURE に移行します。

有効化

Activate リクエストは、次の再起動時に準備した更新を有効にします。

rpc Activate(ActivateRequest) returns (ActivateResponse) {}

message ActivateRequest {}

message ActivateResponse {}

再起動前

Update Manager は、更新を有効にしている間、ACTIVATE_PRE_REBOOT 状態に移行します。Update Manager は、システムの再起動時に有効になるユーザーデータ チェックポイントも作成します。

有効化アクションは、更新タイプによって異なります。

  • システム アップデート: システムはインストール後の手順を実行し、次の再起動時に切り替えるブートスロットを設定します。
  • サービス バンドル アップデート: システムは、ステージングされた APEX セッションを有効化の準備ができた状態としてマークします。

システムが更新を正常に有効にすると、状態は ACTIVATE_PRE_REBOOT_COMPLETE に移行します。これは、VM が再起動の準備ができていることを示します。 それ以外の場合、状態は ACTIVATE_PRE_REBOOT_FAILURE に移行します。

再起動後

再起動後、システムはチェックポイント モードで起動します。このモードでは、システムはユーザーデータ パーティションへの変更を永続ストレージに commit しません。システムが更新を正常に commit しなかった場合、これらの変更は初期状態に戻ります。

ブートの上限

システムは、次のいずれかの条件でユーザーデータ パーティションへの変更を元に戻します。

  • クライアントが明示的な Rollback() リクエストを送信し、システムを再起動した場合。
  • クライアントが Commit() または Rollback() を呼び出さずに、システムが何度も起動した場合。ブートの上限は、更新タイプによって異なります。
    • システム アップデート: BootControl 実装で設定します。たとえば、Cuttlefish デバイスで使用される実装のデフォルトの上限は7 回の起動です。
    • サービス バンドル アップデート: クライアントが提供する ServiceBundleUpdatePayloadboot_attempts フィールドは、Prepare() リクエストが行われたときに設定されます。
確認

次に、システムは更新を検証します。

  • システム アップデート: dm-verity は、更新されたスロットの破損をチェックします。
  • サービス バンドル アップデート: apexd は各 APEX の署名をチェックし、APEX のイメージをファイル システムにマウントします。

検証に成功すると、状態は ACTIVATE_POST_REBOOT_COMPLETE に移行します。Update Manager は Commit() または Rollback() を待ちます。

検証に失敗すると、システムが再起動します。システムがブート の上限に達すると、システムは元の状態に戻ります。

  • システム アップデート: システムは元のスロットに戻ります。
  • サービス バンドル アップデート: 更新された APEX は削除され、元の APEX が再度有効になります。

どの更新タイプでも検証に失敗した場合、元の状態が復元された後、状態は ACTIVATE_PRE_REBOOT_FAILURE に移行します。

ロールバック

Rollback リクエストは、システムを更新前の状態に戻す処理を開始します。

rpc Rollback(RollbackRequest) returns (RollbackResponse) {}

message RollbackRequest {}

message RollbackResponse {}

Rollback() リクエストは、多くの状態で実行できます。初期状態に応じて、システムは異なるアクションを実行し、異なる状態が続きます。

ロールバックが発行されたときの状態 状態遷移 システム アクション
(システム アップデートのみ)PREPAREPREPARE_SUSPEND_COMPLETE &rightarrow; PREPARE_CANCEL &rightarrow; PREPARE_ROLLBACK &rightarrow; READY システム アップデート: システム アップデートをキャンセルします。
PREPARE_FAILUREPREPARE_COMPLETE &rightarrow; PREPARE_ROLLBACK &rightarrow; READY システム アップデート: システム アップデートをキャンセルします。

サービス バンドル アップデート: ステージングされた APEX セッションを中止します。
ACTIVATE_PRE_REBOOT_COMPLETEACTIVATE_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 に移行します。

commit

このリクエストは、更新が正常に完了し、すべての変更が永続的に適用されたことを示します。

rpc Commit(CommitRequest) returns (CommitResponse) {}

message CommitRequest {}

message CommitResponse {}

commit アクションの実行中に、状態が COMMIT に移行します。

  • システム アップデート: Update Manager はブートを成功としてマークします。これにより、今後のロールバックが防止され、以降のブートでこのスロットが選択されます。
  • サービス バンドル アップデート: Update Manager は、ステージングされた APEX セッションを成功としてマークし、更新セッションを終了して、バンドルを永続的に有効にします。

システムが更新を commit すると、Update Manager はユーザーデータ チェックポイントを commit します。システムは、このブート中に書き込まれたすべての新しいユーザーデータを永続ストレージに commit します。Update Manager は READY に戻り、更新が完了したことを示します。

APEX をアンインストールする

UninstallApex リクエストは、サービス バンドルの /data バージョンを削除します。UninstallApex はどの状態でも呼び出すことができますが、アンインストールを有効にするには VM を再起動する必要があります。そのため、更新が進行中に 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 {}