تقليل حجم التحديثات عبر الهواء

توضّح هذه الصفحة التغييرات التي تمت إضافتها إلى AOSP للحدّ من التغييرات غير الضرورية في الملفات بين الإصدارات. يمكن لمصنّعي الأجهزة الذين يحتفظون بأنظمة الإصدار الخاصة بهم استخدام هذه المعلومات كدليل لتقليل حجم التحديثات عبر الأثير (OTA).

تحتوي تحديثات Android عبر الأثير (OTA) أحيانًا على ملفات تم تغييرها ولا تتوافق مع تغييرات الرموز. وهي في الواقع عناصر نظام الإنشاء. يمكن أن يحدث ذلك عندما ينتج عدد كبير من الملفات المتغيرة عن الرمز البرمجي نفسه الذي تم إنشاؤه في أوقات مختلفة أو من أدلة مختلفة أو على أجهزة مختلفة. تؤدي هذه الملفات الزائدة إلى زيادة حجم حزمة OTA، ويصعب تحديد الرمز الذي تم تغييره.

لزيادة شفافية محتوى تحديثات البرامج عبر الأثير، يتضمّن مشروع AOSP تغييرات في نظام الإنشاء مصمَّمة لتقليل حجم حِزم تصحيح تحديثات البرامج عبر الأثير. تمت إزالة تغييرات الملفات غير الضرورية بين الإصدارات، ولم يتم تضمين سوى الملفات ذات الصلة بالحزمة في تحديثات OTA. يتضمّن AOSP أيضًا أداة مقارنة بين الإصدارات، والتي تعمل على فلترة التغييرات الشائعة في الملفات المرتبطة بالإصدار لتوفير مقارنة أوضح بين ملفات الإصدار، وأداة ربط بين الوحدات، والتي تساعدك في الحفاظ على اتساق عملية تخصيص الوحدات.

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

  • استخدام ZSTD، وهي خوارزمية عامة الغرض لضغط البيانات بدون فقدانها، وذلك للصور الكاملة عند تحديث الأجهزة التي لا تستخدم نظام التشغيل A/B يمكن تخصيص ZSTD للحصول على نسب ضغط أعلى من خلال زيادة مستوى الضغط. يتم ضبط مستوى الضغط أثناء إنشاء حزمة OTA، ويمكن ضبطه من خلال تمرير العلامة --vabc_compression_param=zstd,$COMPRESSION_LEVEL
  • زيادة حجم نافذة الضغط المستخدَمة أثناء التحديث عبر الهواء يمكن ضبط الحد الأقصى لحجم نافذة الضغط من خلال تخصيص مَعلمة الإصدار في ملف .mk على الجهاز. يتم ضبط هذا المتغيّر على النحو التالي: PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 262144
  • استخدام أداة إعادة الضغط Puffin، وهي أداة تصحيح حتمية لتدفقات deflate، تتعامل مع وظائف الضغط والاختلاف لإنشاء تحديثات A/B عبر اتصال لاسلكي.
  • تغييرات على استخدام أداة إنشاء دلتا، مثل طريقة استخدام مكتبة bsdiff لضغط حِزم التصحيح في نظام التشغيل Android 9 والإصدارات الأحدث، تختار الأداة bsdiff خوارزمية الضغط التي ستحقّق أفضل نتائج ضغط لحزمة.
  • أدّت التحسينات التي تم إجراؤها على update_engine إلى تقليل مساحة الذاكرة المستهلكة عند تطبيق رموز التصحيح لتحديثات أجهزة اختبار A/B.

تناقش الأقسام التالية المشاكل المختلفة التي تؤثر في أحجام تحديثات OTA، وحلولها، وأمثلة على التنفيذ في AOSP.

ترتيب الملفات

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

الحل: عند استخدام أدوات مثل find وmake مع دالة حرف البدل، رتِّب ناتج هذه الأوامر قبل استخدامها. عند استخدام $(wildcard) أو $(shell find) في ملفات Android.mk، يجب ترتيبها أيضًا. بعض الأدوات، مثل Java، ترتّب المدخلات، لذا قبل ترتيب الملفات، تأكَّد من أنّ الأداة التي تستخدمها لم تفعل ذلك من قبل.

أمثلة: تم إصلاح العديد من المشاكل في نظام الإنشاء الأساسي باستخدام الماكرو all-*-files-under المضمّن، والذي يتضمّن all-cpp-files-under (بما أنّ العديد من التعريفات كانت موزّعة في ملفات makefile أخرى). لمزيد من التفاصيل، يُرجى الاطّلاع على ما يلي:

إنشاء دليل

المشكلة: يمكن أن يؤدي تغيير الدليل الذي يتم فيه إنشاء العناصر إلى اختلاف البرامج الثنائية. معظم المسارات في إصدار Android هي مسارات نسبية، لذا لا تشكّل __FILE__ في C/C++ مشكلة. ومع ذلك، تشفّر رموز تصحيح الأخطاء اسم المسار الكامل تلقائيًا، ويتم إنشاء .note.gnu.build-id من خلال تجزئة الرمز الثنائي الذي تم إزالة أجزاء منه مسبقًا، لذا سيتغيّر إذا تغيّرت رموز تصحيح الأخطاء.

الحل: أصبحت مسارات تصحيح الأخطاء في AOSP نسبية. للحصول على التفاصيل، يُرجى الرجوع إلى CL: https://android.googlesource.com/platform/build/+/6a66a887baadc9eb3d0d60e26f748b8453e27a02.

الطوابع الزمنية

المشكلة: تؤدي الطوابع الزمنية في ناتج الإنشاء إلى تغييرات غير ضرورية في الملفات. من المحتمل أن يحدث ذلك في المواقع الجغرافية التالية:

  • __DATE__/__TIME__/__TIMESTAMP__ وحدات ماكرو في رمز C أو C++‎
  • طوابع زمنية مضمّنة في أرشيفات مستندة إلى ملفات zip

الحلول/الأمثلة: لإزالة الطوابع الزمنية من ناتج الإنشاء، اتّبِع التعليمات الواردة أدناه في __DATE__/__TIME__/__TIMESTAMP__ في C/C++. و الطوابع الزمنية المضمّنة في الأرشيفات.

‫__DATE__/__TIME__/__TIMESTAMP__ في C/C++

تنتج وحدات الماكرو هذه دائمًا نواتج مختلفة للإصدارات المختلفة، لذا لا تستخدِمها. في ما يلي بعض الخيارات لإزالة وحدات الماكرو هذه:

الطوابع الزمنية المضمّنة في الأرشيفات (zip وjar)

حلّ الإصدار 7.0 من نظام التشغيل Android مشكلة الطوابع الزمنية المضمّنة في أرشيفات zip من خلال إضافة -X إلى جميع استخدامات الأمر zip. أدّى ذلك إلى إزالة معرّف المستخدم/المجموعة (UID/GID) الخاصين ببرنامج الإنشاء والطابع الزمني الموسّع لنظام التشغيل Unix من ملف ZIP.

تعمل أداة جديدة، ziptime (الموجودة في /platform/build/+/android16-release/tools/ziptime/)، على إعادة ضبط الطوابع الزمنية العادية في عناوين ملفات zip. للاطّلاع على التفاصيل، يُرجى الرجوع إلى ملف README.

تضبط أداة signapk الطوابع الزمنية لملفات APK التي قد تختلف حسب المنطقة الزمنية للخادم. للاطّلاع على التفاصيل، يُرجى الرجوع إلى قائمة التغيير https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028.

تضبط أداة signapk الطوابع الزمنية لملفات APK التي قد تختلف حسب المنطقة الزمنية للخادم. للاطّلاع على التفاصيل، يُرجى الرجوع إلى قائمة التغيير https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028.

سلاسل الإصدار

المشكلة: غالبًا ما كانت تتم إضافة BUILD_NUMBER إلى سلاسل إصدارات حِزم APK المرمّزة ثابتًا. وحتى إذا لم يتغيّر أي شيء آخر في حزمة APK، سيظل الاختلاف موجودًا.

الحل: أزِل رقم الإصدار من سلسلة إصدار APK.

أمثلة:

تفعيل احتساب صحة البيانات على الجهاز

في حال تفعيل dm-verity على جهازك، ستختار أدوات التحديث عبر الهواء تلقائيًا إعدادات التحقّق من صحة التوقيع، وسيتم تفعيل عملية التحقّق من صحة التوقيع على الجهاز. يتيح ذلك إمكانية احتساب كتل التحقق على أجهزة Android، بدلاً من تخزينها كبايتات أولية في حزمة OTA. يمكن أن تستخدم وحدات Verity حوالي 16 ميغابايت لقسم بسعة 2 غيغابايت.

ومع ذلك، قد يستغرق حساب صحة البيانات على الجهاز وقتًا طويلاً. على وجه التحديد، قد يستغرق رمز تصحيح الخطأ الأمامي وقتًا طويلاً. على أجهزة Pixel، تستغرق هذه العملية عادةً مدة تصل إلى 10 دقائق. وقد يستغرق الأمر وقتًا أطول على الأجهزة الأقل تطوّرًا. إذا أردت إيقاف عملية احتساب صحة البيانات على الجهاز، مع إبقاء dm-verity مفعّلاً، يمكنك إجراء ذلك عن طريق تمرير --disable_fec_computation إلى أداة ota_from_target_files عند إنشاء تحديث عبر الأثير (OTA). يؤدي هذا الخيار إلى إيقاف احتساب صحة البيانات على الجهاز أثناء التحديثات عبر الأثير. يقلّل هذا الخيار من وقت تثبيت تحديث OTA، ولكنّه يزيد من حجم حزمة OTA. إذا لم يكن جهازك مفعّلاً عليه dm-verity، لن يكون لتمرير هذا العلامة أي تأثير.

أدوات إنشاء متوافقة

المشكلة: يجب أن تكون الأدوات التي تنشئ الملفات المثبَّتة متسقة (يجب أن يؤدي الإدخال نفسه دائمًا إلى الناتج نفسه).

الحلول/الأمثلة: كانت هناك حاجة إلى إجراء تغييرات في أدوات الإنشاء التالية:

استخدام أداة مقارنة الإصدارات

في الحالات التي لا يمكن فيها إزالة تغييرات الملفات المرتبطة بعملية الإنشاء، يتضمّن مشروع AOSP أداة مقارنة بين عمليات الإنشاء، target_files_diff.py يمكن استخدامها لمقارنة حزمتَي ملفات. تُجري هذه الأداة عملية مقارنة متكررة بين إصدارَين، مع استبعاد التغييرات الشائعة في الملفات ذات الصلة بالإصدار، مثل

  • التغييرات المتوقّعة في ناتج الإصدار (على سبيل المثال، بسبب تغيير رقم الإصدار)
  • تغييرات بسبب مشاكل معروفة في نظام الإصدار الحالي

لاستخدام أداة مقارنة الإصدارات، شغِّل الأمر التالي:

target_files_diff.py dir1 dir2

dir1 وdir2 هما دليلان أساسيان يحتويان على الملفات المستهدَفة التي تم استخراجها لكل إصدار.

الحفاظ على اتّساق عملية تخصيص الحظر

بالنسبة إلى ملف معيّن، على الرغم من أنّ محتواه يظل كما هو بين إصدارَين، قد تكون الكتل الفعلية التي تحتوي على البيانات قد تغيّرت. ونتيجةً لذلك، يجب أن ينفّذ برنامج التحديث عمليات إدخال/إخراج غير ضرورية لنقل الوحدات من أجل إجراء تحديث عبر الأثير.

في تحديث Virtual A/B عبر الأثير، يمكن أن تؤدي عمليات الإدخال/الإخراج غير الضرورية إلى زيادة كبيرة في مساحة التخزين المطلوبة لتخزين اللقطة التي يتم نسخها عند الكتابة. في التحديثات الهوائية غير المتوافقة مع نظام التشغيل A/B، يؤدي نقل الوحدات إلى أماكن أخرى لإجراء تحديث هوائي إلى زيادة وقت التحديث بسبب زيادة عمليات الإدخال والإخراج الناتجة عن عمليات نقل الوحدات.

لحلّ هذه المشكلة، وسّعت Google في الإصدار 7.0 من نظام التشغيل Android نطاق استخدام الأداة make_ext4fs لتوفير اتساق في عملية تخصيص الحِزم على مستوى جميع الإصدارات. تقبل الأداة make_ext4fs العلامة الاختيارية -d base_fs التي تحاول تخصيص الملفات لنفس الحِزم عند إنشاء صورة ext4. يمكنك استخراج ملفات ربط الحِزم (مثل ملفات الخريطة base_fs) من ملف ZIP الخاص بالملفات المستهدَفة لإصدار سابق. لكل قسم ext4، يتوفّر ملف .map في الدليل IMAGES (على سبيل المثال، يتوافق IMAGES/system.map مع القسم system). يمكن بعد ذلك تسجيل هذه الملفات base_fs وتحديدها باستخدام PRODUCT_<partition>_BASE_FS_PATH، كما في المثال التالي:

  PRODUCT_SYSTEM_BASE_FS_PATH := path/to/base_fs_files/base_system.map
  PRODUCT_SYSTEM_EXT_BASE_FS_PATH := path/to/base_fs_files/base_system_ext.map
  PRODUCT_VENDOR_BASE_FS_PATH := path/to/base_fs_files/base_vendor.map
  PRODUCT_PRODUCT_BASE_FS_PATH := path/to/base_fs_files/base_product.map
  PRODUCT_ODM_BASE_FS_PATH := path/to/base_fs_files/base_odm.map

على الرغم من أنّ ذلك لا يساعد في تقليل حجم حزمة OTA الإجمالية، إلا أنّه يحسّن أداء تحديث OTA من خلال تقليل مقدار عمليات الإدخال والإخراج. بالنسبة إلى تحديثات Virtual A/B، فإنّها تقلّل بشكل كبير من مساحة التخزين المطلوبة لتطبيق التحديث عبر الأثير.

تجنُّب تحديث التطبيقات

بالإضافة إلى تقليل الاختلافات بين الإصدارات، يمكنك تقليل أحجام تحديثات OTA من خلال استبعاد التحديثات للتطبيقات التي تتلقّى تحديثات من خلال متاجر التطبيقات. وغالبًا ما تشكّل حِزم APK جزءًا كبيرًا من الأقسام المختلفة على الجهاز. قد يؤدي تضمين أحدث إصدارات التطبيقات التي يتم تحديثها من خلال متاجر التطبيقات في حزمة تحديث عبر الأثير إلى زيادة حجم الحزمة بشكل كبير، مع تحقيق فائدة قليلة للمستخدم. عندما يتلقّى المستخدمون حزمة OTA، قد يكون لديهم التطبيق المحدَّث أو إصدار أحدث منه تم تلقّيه مباشرةً من متاجر التطبيقات.