Pengelola Update

Update Manager melakukan update untuk VM-nya. Update Manager berkoordinasi dengan klien, yang disediakan oleh integrator sistem. Klien menyediakan payload update dan mengoordinasikan update kendaraan secara keseluruhan. Update terdiri dari langkah-langkah berikut:

  1. READY: Tidak ada update yang sedang berlangsung.
  2. PREPARE: Update Manager menulis update ke disk, tetapi tidak mengaktifkannya.
  3. ACTIVATE: Update Manager mengaktifkan update yang telah disiapkan sehingga berlaku setelah reboot.
  4. COMMIT: Update Manager membuat update bersifat permanen.

Mesin status yang disederhanakan yang mengilustrasikan alur kerja Pengelola Update

Gambar 1. Operasi tingkat tinggi Update Manager.

Update Manager mendukung update sistem dan update paket layanan, yang dijelaskan di halaman ini.

Update sistem

Android OS menggunakan dua set partisi yang disebut slot, dengan hanya satu slot aktif dalam satu waktu. Update sistem menulis set partisi baru ke slot yang tidak aktif, dan sistem akan mengalihkan slot aktif pada reboot berikutnya. Untuk mengetahui informasi selengkapnya tentang membuat update sistem, lihat Update sistem A/B.

Update paket layanan

Di AAOS SDV, paket layanan mengemas layanan bersama dalam APEX. Update paket layanan menempatkan file APEX baru dalam sesi sementara. Sistem mengaktifkan paket yang diupdate ini setelah reboot sistem. Untuk mengetahui informasi selengkapnya tentang membuat APEX paket layanan, lihat Update paket layanan.

Mesin status

Permintaan dari klien dan peristiwa dari layanan sistem mendorong mesin status Update Manager. Update Manager dirancang agar tangguh, memulihkan statusnya, dan melanjutkan proses update bahkan setelah reboot atau error yang tidak terduga.

Mesin status yang mengilustrasikan alur kerja Pengelola Update

Gambar 2. Mesin status Update Manager.

API

Update Manager menyediakan API yang mendorong proses update melalui mesin status. API menggunakan VSIDL, yang mendukung klien yang berada di VM mana pun yang mendukung SDV Comms dan memberikan notifikasi kegagalan permintaan.

Keamanan dan akses

Sistem membatasi akses API menggunakan kebijakan otorisasi. Hanya klien yang diotorisasi yang dapat melakukan panggilan ke Update Manager.

Pembaruan status

Karena operasi update dapat berjalan lama, Update Manager menyediakan pembaruan status asinkron. Klien harus memantau status dengan berlangganan pembaruan status.

Pengelolaan langganan

  • Berlangganan: Klien berlangganan pembaruan status dengan memanggil metode SubscribeToStatusUpdates():

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

    Sebelum memanggil SubscribeToStatusUpdates(), klien harus memulai antarmuka RPC yang mengimplementasikan UpdateManagerListenerService.

  • Berhenti berlangganan: Klien dapat berhenti menerima pembaruan status dengan memanggil UnsubscribeFromStatusUpdates():

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

UpdateManagerListenerService

Klien yang memanggil SubscribeToStatusUpdates() di UpdateManagerService harus mengimplementasikan layanan berikut untuk menerima pembaruan 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 {}

OnStatusUpdateRequest mengirimkan salah satu dari dua kemungkinan pesan menggunakan kolom status_update:

  1. UpdateManagerStatus: Dikirim saat status Update Manager berubah.
  2. UpdateProgress: Dikirim untuk menunjukkan progres update selama status PREPARE dan ACTIVATE_PRE_REBOOT karena prosesnya dapat memerlukan waktu yang cukup lama.

Status dan pesan error

Pesan status mencakup detail tentang status dan kegagalan apa pun:

  • UpdateManagerStatus: Melaporkan fase update saat ini dan alasan kegagalan:

    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: Melaporkan status saat ini dari Update Engine selama update sistem:

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

Mendapatkan status langsung

Anda dapat mengambil status dan payload saat ini kapan saja dengan memanggil GetStatus(). Pesan SystemUpdatePayload dan ServiceBundleUpdatePayload dijelaskan di bagian Persiapan.

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

Persiapan

Permintaan Prepare memulai proses update dengan menempatkan payload, tetapi sistem menunggu untuk mengaktifkan update:

rpc Prepare(PrepareRequest) returns (PrepareResponse) {}

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

message PrepareResponse {}

Jika permintaan valid, status akan bertransisi ke PREPARE, dan Update Manager akan memulai update.

Jenis payload menentukan jenis update.

Payload update sistem

Update sistem menggunakan data SystemUpdatePayload, yang memerlukan jalur ke image update over-the-air (OTA). Parameter lainnya diuraikan dari image, tetapi Anda dapat menentukannya untuk mengganti nilai yang diuraikan.

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 memproses image OTA (disediakan oleh klien di direktori /data/ota_package) untuk menjalankan langkah-langkah pasca-penginstalan, tetapi tidak mengalihkan slot boot aktif. Kemudian, status akan bertransisi ke status PREPARE_COMPLETE jika berhasil atau status PREPARE_FAILURE jika gagal.

Penangguhan update sistem

Anda hanya dapat menjeda proses update untuk update sistem. Permintaan ini hanya valid saat dalam status PREPARE.

  • Suspend: Menjeda update, mentransisikan status melalui PREPARE_SUSPEND.

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

    Jika berhasil, status akan bertransisi ke PREPARE_SUSPEND_COMPLETE. Jika gagal, status akan bertransisi ke PREPARE_FAILURE.

  • Resume: Melanjutkan update yang dijeda. Status ini hanya valid dalam status PREPARE_SUSPEND_COMPLETE.

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

    Status akan bertransisi kembali ke status PREPARE.

Payload update paket layanan

Update paket layanan menggunakan ServiceBundleUpdatePayload, yang berisi jalur ke file APEX dan menetapkan batas percobaan aktivasi.

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 memverifikasi bahwa file APEX ditandatangani dengan benar dan menempatkannya dalam sesi. Jika berhasil, status akan bertransisi ke PREPARE_COMPLETE. Jika gagal, status akan bertransisi ke PREPARE_FAILURE.

Aktifkan

Permintaan Activate mengaktifkan update yang telah disiapkan pada reboot berikutnya.

rpc Activate(ActivateRequest) returns (ActivateResponse) {}

message ActivateRequest {}

message ActivateResponse {}

Pra-reboot

Update Manager bertransisi ke status ACTIVATE_PRE_REBOOT saat mengaktifkan update. Update Manager juga membuat checkpoint data pengguna yang berlaku saat sistem di-reboot.

Tindakan aktivasi berbeda-beda bergantung pada jenis update:

  • Update sistem: Sistem menjalankan langkah-langkah pasca-penginstalan dan menetapkan slot boot untuk diaktifkan pada reboot berikutnya.
  • Update paket layanan: Sistem menandai sesi APEX yang ditempatkan sebagai siap untuk diaktifkan.

Jika sistem berhasil mengaktifkan update, status akan bertransisi ke ACTIVATE_PRE_REBOOT_COMPLETE, yang menunjukkan bahwa VM siap untuk di-reboot. Jika tidak, status akan bertransisi ke ACTIVATE_PRE_REBOOT_FAILURE.

Setelah reboot

Setelah reboot, sistem akan dimulai dalam mode checkpoint. Dalam mode ini, sistem tidak melakukan perubahan apa pun pada partisi data pengguna ke penyimpanan permanen. Jika sistem tidak berhasil melakukan update, sistem akan mengembalikan perubahan ini ke status awal.

Batas boot

Sistem akan mengembalikan perubahan ke partisi data pengguna dalam salah satu kondisi berikut:

  • Klien mengirimkan permintaan Rollback() eksplisit dan me-reboot sistem.
  • Sistem melakukan booting terlalu sering tanpa klien memanggil Commit() atau Rollback(). Batas boot berbeda untuk setiap jenis update:
    • Update sistem: Implementasi BootControl menetapkan batas ini. Misalnya, batas default dalam implementasi yang digunakan oleh perangkat Cuttlefish adalah tujuh boot.
    • Update paket layanan: Kolom boot_attempts dari ServiceBundleUpdatePayload yang disediakan oleh klien menetapkan batas ini saat permintaan Prepare() dibuat.
Verifikasi

Kemudian, sistem akan memverifikasi update:

  • Update sistem: dm-verity memeriksa slot yang diupdate untuk mengetahui kerusakan.
  • Update paket layanan: apexd memeriksa tanda tangan setiap APEX dan memasang image APEX ke sistem file.

Jika verifikasi berhasil, status akan bertransisi ke ACTIVATE_POST_REBOOT_COMPLETE. Update Manager menunggu Commit() atau Rollback().

Jika verifikasi gagal, sistem akan di-reboot. Saat sistem mencapai batas boot limit, sistem akan kembali ke status awal:

  • Update sistem: Sistem kembali ke slot asli.
  • Update paket layanan: APEX yang diupdate akan dihapus, dan APEX asli akan diaktifkan kembali.

Jika verifikasi gagal untuk jenis update apa pun, status akan bertransisi ke ACTIVATE_PRE_REBOOT_FAILURE setelah status asli dipulihkan.

Rollback

Permintaan Rollback mulai mengembalikan sistem ke status pra-update.

rpc Rollback(RollbackRequest) returns (RollbackResponse) {}

message RollbackRequest {}

message RollbackResponse {}

Anda dapat membuat permintaan Rollback() selama banyak status. Bergantung pada status awal, sistem akan mengambil tindakan yang berbeda, dan status yang berbeda akan mengikuti:

Status saat rollback dikeluarkan Transisi status Tindakan sistem
(Hanya update sistem) PREPARE, PREPARE_SUSPEND_COMPLETE &rightarrow; PREPARE_CANCEL &rightarrow; PREPARE_ROLLBACK &rightarrow; READY Update sistem: Membatalkan update sistem.
PREPARE_FAILURE, PREPARE_COMPLETE &rightarrow; PREPARE_ROLLBACK &rightarrow; READY Update sistem: Membatalkan update sistem.

Update paket layanan: Membatalkan sesi APEX yang ditempatkan.
ACTIVATE_PRE_REBOOT_COMPLETE, ACTIVATE_PRE_REBOOT_FAILURE &rightarrow; ACTIVATE_PRE_REBOOT_ROLLBACK &rightarrow; READY Menonaktifkan checkpoint data pengguna.

Update sistem: Membatalkan pengalihan slot boot.

Update paket layanan: Menghapus APEX yang ditempatkan.
ACTIVATE_POST_REBOOT_COMPLETE &rightarrow; ACTIVATE_POST_REBOOT_ROLLBACK &rightarrow; ACTIVATE_POST_REBOOT_ROLLBACK_COMPLETE Menonaktifkan checkpoint data pengguna.

Update sistem: Mengalihkan slot boot kembali.

Update paket layanan: Mengembalikan sesi APEX aktif.

Reboot akhir diperlukan agar rollback diterapkan, setelah itu status akan bertransisi ke READY.

Commit

Permintaan ini menunjukkan bahwa update berhasil diselesaikan dan menerapkan semua perubahan secara permanen.

rpc Commit(CommitRequest) returns (CommitResponse) {}

message CommitRequest {}

message CommitResponse {}

Status akan bertransisi ke COMMIT saat melakukan tindakan commit:

  • Update sistem: Update Manager menandai boot sebagai berhasil, yang mencegah rollback di masa mendatang dan memilih slot ini pada boot berikutnya.
  • Update paket layanan: Update Manager menandai sesi APEX yang ditempatkan sebagai berhasil, menutup sesi update, dan membuat paket aktif secara permanen.

Setelah sistem melakukan update, Update Manager akan melakukan checkpoint data pengguna. Sistem melakukan semua data pengguna baru yang ditulis selama boot ini ke penyimpanan permanen. Update Manager bertransisi kembali ke READY, yang menunjukkan bahwa update telah selesai.

Uninstal APEX

Permintaan UninstallApex menghapus paket layanan versi /data. Anda dapat memanggil UninstallApex selama status apa pun, tetapi VM harus di-reboot agar uninstal diterapkan. Oleh karena itu, hindari memanggil UninstallApex saat update sedang berlangsung. UninstallApex tidak menghapus APEX yang sudah diinstal, menghapus data APEX, atau menghapus versi APEX yang tidak aktif.

rpc UninstallApex(UninstallApexRequest) returns (UninstallApexResponse) {}

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

message UninstallApexResponse {}