Update Manager

ينفّذ "مدير التحديثات" التحديثات لجهازه الظاهري. يتواصل "مدير التحديثات" مع العميل الذي يوفّره مُدمِج الأنظمة. يقدّم العميل حمولة التحديث وينسّق عملية تحديث المركبة بشكل عام. يتألف التحديث من الخطوات التالية:

  1. جاهز: ما مِن تحديث قيد التنفيذ.
  2. الإعداد: يكتب "مدير التحديثات" التحديث على القرص، ولكن لا يفعّله.
  3. التفعيل: يفعّل "مدير التحديثات" التحديث الذي تم إعداده ليصبح ساريًا بعد إعادة التشغيل.
  4. الإرسال: يثبّت "مدير التحديثات" التحديث بشكل دائم.

آلة حالة مبسطة توضّح سير عمل "أداة إدارة التحديثات"

الشكل 1: عملية "مدير التحديثات" على المستوى العالي

يتيح "مدير التحديثات" تحديثات النظام وتحديثات حِزم الخدمات، كما هو موضّح في هذه الصفحة.

تحديثات النظام

يستخدم نظام التشغيل Android مجموعتَين من الأقسام تُعرفان باسم الفتحات، ولا تكون سوى فتحة واحدة نشطة في كل مرة. يكتب تحديث النظام مجموعة جديدة من الأقسام في الفتحة غير النشطة، ويغيّر النظام الفتحة النشطة عند إعادة التشغيل التالية. لمزيد من المعلومات حول إنشاء تحديثات النظام، يُرجى الاطّلاع على تحديثات النظام من النوع أ/ب.

تحديثات حِزم الخدمات

في AAOS SDV، تجمّع حِزم الخدمات الخدمات معًا ضمن حِزم APEX. تُعدّ تحديثات حِزم الخدمات ملفات APEX الجديدة في جلسات مؤقتة. يفعّل النظام هذه الحِزم المعدَّلة بعد إعادة تشغيل النظام. لمزيد من المعلومات حول إنشاء حِزم APEX لحِزم الخدمات، يُرجى الاطّلاع على تحديثات حِزم الخدمات.

آلة الحالة

تؤدي الطلبات الواردة من العميل والأحداث الواردة من خدمات النظام إلى تشغيل آلة حالة "مدير التحديثات". تم تصميم "مدير التحديثات" ليكون مرنًا، حيث يسترد حالته ويستأنف عملية التحديث حتى بعد عمليات إعادة التشغيل أو الأعطال غير المتوقّعة.

آلة حالة توضّح سير عمل "أداة التحديث"

الشكل 2: آلة حالة "مدير التحديثات"

واجهة برمجة التطبيقات

يوفّر "مدير التحديثات" واجهة برمجة تطبيقات تُشغّل عملية التحديث من خلال آلة الحالة. تستخدم واجهة برمجة التطبيقات لغة VSIDL التي تتيح للعملاء المقيمين في أي جهاز ظاهري يتيح SDV Comms وتوفّر إشعارًا بفشل الطلب.

الأمان وإمكانية الوصول

يقيّد النظام إمكانية الوصول إلى واجهة برمجة التطبيقات باستخدام سياسات التفويض. يمكن للعميل المفوّض فقط إجراء طلبات إلى "مدير التحديثات".

آخر الأخبار

بما أنّ عمليات التحديث قد تستغرق وقتًا طويلاً، يوفّر "مدير التحديثات" آخر الأخبار غير المتزامنة. على العملاء مراقبة الحالة من خلال الاشتراك في آخر الأخبار.

إدارة الاشتراك

  • الاشتراك: يشترك العملاء في آخر الأخبار من خلال استدعاء طريقة SubscribeToStatusUpdates():

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

    قبل استدعاء SubscribeToStatusUpdates()، على العميل بدء واجهة RPC التي تنفّذ UpdateManagerListenerService.

  • إلغاء الاشتراك: يمكن للعملاء التوقف عن تلقّي آخر الأخبار من خلال استدعاء UnsubscribeFromStatusUpdates():

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

UpdateManagerListenerService

على العملاء الذين يستدعون SubscribeToStatusUpdates() على UpdateManagerService تنفيذ الخدمة التالية لتلقّي آخر الأخبار:

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: يتم إرسالها عند تغيُّر حالة "مدير التحديثات".
  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: تعرض الحالة الحالية من محرك التحديث أثناء تحديثات النظام:

    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، ويبدأ "مدير التحديثات" التحديث.

يحدد نوع الحمولة نوع التحديث.

حمولة تحديث النظام

يستخدم تحديث النظام بيانات 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;
}

يعالج "مدير التحديثات" صورة 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.

حمولة تحديث حِزمة الخدمات

يستخدم تحديث حِزمة الخدمات ServiceBundleUpdatePayload الذي يحتوي على مسارات ملفات APEX ويضبط الحد الأقصى لمحاولات التفعيل.

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

يتحقّق "مدير التحديثات" من توقيع ملفات APEX بشكل صحيح ويُعدّها في جلسة. في حال النجاح، تنتقل الحالة إلى PREPARE_COMPLETE. في حال الفشل، تنتقل الحالة إلى PREPARE_FAILURE.

تفعيل

يؤدي طلب Activate إلى تفعيل التحديث الذي تم إعداده عند إعادة التشغيل التالية.

rpc Activate(ActivateRequest) returns (ActivateResponse) {}

message ActivateRequest {}

message ActivateResponse {}

قبل إعادة التشغيل

ينتقل "مدير التحديثات" إلى الحالة ACTIVATE_PRE_REBOOT أثناء تفعيل التحديث. ينشئ "مدير التحديثات" أيضًا نقطة تحقّق من بيانات المستخدمين تصبح سارية عند إعادة تشغيل النظام.

تختلف إجراءات التفعيل حسب نوع التحديث:

  • تحديث النظام: ينفّذ النظام خطوات ما بعد التثبيت ويضبط فتحة الإقلاع ليتم تغييرها عند إعادة التشغيل التالية.
  • تحديث حِزمة الخدمات: يضع النظام علامة على جلسة APEX التي تم إعدادها للإشارة إلى أنّها جاهزة للتفعيل.

إذا فعّل النظام التحديث بنجاح، تنتقل الحالة إلى ACTIVATE_PRE_REBOOT_COMPLETE، ما يشير إلى أنّ الجهاز الظاهري جاهز لإعادة التشغيل. وإلا، تنتقل الحالة إلى ACTIVATE_PRE_REBOOT_FAILURE.

بعد إعادة التشغيل

بعد إعادة التشغيل، يبدأ النظام في وضع نقطة التحقّق. في هذا الوضع، لا يرسل النظام أي تغييرات إلى قسم بيانات المستخدمين في وحدة التخزين الدائمة. إذا لم يرسل النظام التحديث بنجاح، يعود إلى الحالة الأولية.

الحد الأقصى لعمليات الإقلاع

يعود النظام إلى التغييرات التي تم إجراؤها على قسم بيانات المستخدمين في أي من الحالتَين التاليتَين:

  • يرسل العميل طلب Rollback() صريحًا ويعيد تشغيل النظام.
  • يُقلع النظام عدة مرات بدون أن يستدعي العميل Commit() أو Rollback(). يختلف الحد الأقصى لعمليات الإقلاع حسب نوع التحديث:
    • تحديث النظام: يضبط هذا الإعداد تنفيذ BootControl. على سبيل المثال، الحد الأقصى التلقائي في التنفيذ الذي تستخدمه أجهزة Cuttlefish هو سبع عمليات إقلاع.
    • تحديث حِزمة الخدمات: يضبط هذا الإعداد الحقل boot_attempts في ServiceBundleUpdatePayload الذي يوفّره العميل عند إجراء طلب Prepare().
إثبات الهوية

بعد ذلك، يتحقّق النظام من التحديث:

  • تحديث النظام: يتحقّق dm-verity من الفتحة المعدَّلة بحثًا عن أي تلف.
  • تحديث حِزمة الخدمات: يتحقّق apexd من توقيع كل حِزمة APEX ويحمّل صورة حِزمة APEX على نظام الملفات.

إذا نجح التحقّق، تنتقل الحالة إلى ACTIVATE_POST_REBOOT_COMPLETE. ينتظر "مدير التحديثات" Commit() أو Rollback().

إذا فشل التحقّق، يعيد النظام التشغيل. عندما يصل النظام إلى الحد الأقصى لعمليات الإقلاع boot limit، يعود إلى الحالة الأصلية:

  • تحديث النظام: يعود النظام إلى الفتحة الأصلية.
  • تحديث حِزمة الخدمات: يتم حذف حِزم APEX المعدَّلة وإعادة تفعيل حِزم APEX الأصلية.

إذا فشل التحقّق لأي نوع تحديث، تنتقل الحالة إلى ACTIVATE_PRE_REBOOT_FAILURE بعد استعادة الحالة الأصلية.

العودة إلى الحالة السابقة

يبدأ طلب Rollback في إعادة النظام إلى حالته قبل التحديث.

rpc Rollback(RollbackRequest) returns (RollbackResponse) {}

message RollbackRequest {}

message RollbackResponse {}

يمكنك إجراء طلب Rollback() خلال العديد من الحالات. اعتمادًا على الحالة الأولية، يتخذ النظام إجراءات مختلفة، وتتبع حالات مختلفة:

الحالة عند إصدار عملية العودة إلى الحالة السابقة انتقال الحالة إجراء النظام
(تحديث النظام فقط) PREPARE وPREPARE_SUSPEND_COMPLETE &rightarrow; PREPARE_CANCEL &rightarrow; PREPARE_ROLLBACK &rightarrow; READY تحديث النظام: يؤدي إلى إلغاء تحديث النظام.
PREPARE_FAILURE وPREPARE_COMPLETE &rightarrow; PREPARE_ROLLBACK &rightarrow; READY تحديث النظام: يؤدي إلى إلغاء تحديث النظام.

تحديث حِزمة الخدمات: يؤدي إلى إيقاف جلسة APEX التي تم إعدادها.
ACTIVATE_PRE_REBOOT_COMPLETE وACTIVATE_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.

إرسال الطبقات

يشير هذا الطلب إلى اكتمال التحديث بنجاح وتطبيق جميع التغييرات بشكل دائم.

rpc Commit(CommitRequest) returns (CommitResponse) {}

message CommitRequest {}

message CommitResponse {}

تنتقل الحالة إلى COMMIT أثناء تنفيذ إجراءات الإرسال:

  • تحديث النظام: يضع "مدير التحديثات" علامة على عملية الإقلاع للإشارة إلى نجاحها، ما يمنع العودة إلى الحالة السابقة في المستقبل ويختار هذه الفتحة في عمليات الإقلاع اللاحقة.
  • تحديث حِزمة الخدمات: يضع "مدير التحديثات" علامة على جلسة APEX التي تم إعدادها للإشارة إلى نجاحها، ما يؤدي إلى إغلاق جلسة التحديث وتفعيل الحِزم بشكل دائم.

بعد أن يرسل النظام التحديث، يرسل "مدير التحديثات" نقطة التحقّق من بيانات المستخدمين. يرسل النظام جميع بيانات المستخدمين الجديدة التي تمّت كتابتها أثناء عملية الإقلاع هذه إلى وحدة التخزين الدائمة. يعود "مدير التحديثات" إلى READY، ما يشير إلى اكتمال التحديث.

إلغاء تثبيت حِزم APEX

يزيل طلب UninstallApex إصدار /data من حِزم الخدمات. يمكنك استدعاء UninstallApex في أي حالة، ولكن يجب إعادة تشغيل الجهاز الظاهري لتصبح عملية إلغاء التثبيت سارية. لذلك، تجنَّب استدعاء 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 {}