اندازه OTA را کاهش دهید

این صفحه تغییرات اضافه شده به AOSP را برای کاهش تغییرات غیرضروری فایل بین نسخه‌های مختلف شرح می‌دهد. پیاده‌سازی‌کنندگان دستگاه که سیستم‌های ساخت خود را نگهداری می‌کنند، می‌توانند از این اطلاعات به عنوان راهنمایی برای کاهش حجم به‌روزرسانی‌های بی‌سیم (OTA) خود استفاده کنند.

به‌روزرسانی‌های OTA اندروید گاهی اوقات حاوی فایل‌های تغییر یافته‌ای هستند که با تغییرات کد مطابقت ندارند. آن‌ها در واقع مصنوعات سیستمی ساخته شده هستند. این می‌تواند زمانی رخ دهد که یک کد مشابه، که در زمان‌های مختلف، از دایرکتوری‌های مختلف یا روی دستگاه‌های مختلف ساخته شده است، تعداد زیادی فایل تغییر یافته تولید کند. چنین فایل‌های اضافی، اندازه یک پچ OTA را افزایش می‌دهند و تشخیص اینکه کدام کد تغییر کرده است را دشوار می‌کنند.

برای شفاف‌تر کردن محتوای یک OTA، AOSP شامل تغییرات سیستم ساخت است که برای کاهش اندازه پچ‌های OTA طراحی شده‌اند. تغییرات غیرضروری فایل بین ساخت‌ها حذف شده‌اند و فقط فایل‌های مرتبط با پچ در به‌روزرسانی‌های OTA موجود هستند. AOSP همچنین شامل یک ابزار تفاوت ساخت است که تغییرات رایج فایل مرتبط با ساخت را فیلتر می‌کند تا تفاوت فایل ساخت تمیزتری ارائه دهد و یک ابزار نگاشت بلوک است که به شما کمک می‌کند تخصیص بلوک را ثابت نگه دارید.

یک سیستم ساخت می‌تواند به چندین روش پچ‌های غیرضروری و بزرگ ایجاد کند. برای کاهش این مشکل، در اندروید ۸.۰ و بالاتر، ویژگی‌های جدیدی برای کاهش اندازه پچ برای هر تفاوت فایل پیاده‌سازی شده است. بهبودهایی که اندازه بسته‌های به‌روزرسانی OTA را کاهش داده‌اند عبارتند از:

  • استفاده از ZSTD ، یک الگوریتم فشرده‌سازی عمومی و بدون اتلاف برای تصاویر کامل در به‌روزرسانی‌های دستگاه‌های غیر A/B. ZSTD را می‌توان با افزایش سطح فشرده‌سازی برای نسبت‌های فشرده‌سازی بالاتر سفارشی‌سازی کرد. سطح فشرده‌سازی در طول زمان تولید OTA تنظیم می‌شود و می‌توان آن را با ارسال پرچم --vabc_compression_param=zstd,$COMPRESSION_LEVEL تنظیم کرد.
  • افزایش اندازه پنجره فشرده‌سازی مورد استفاده در طول OTA. حداکثر اندازه پنجره فشرده‌سازی را می‌توان با سفارشی‌سازی پارامتر ساخت در فایل .mk دستگاه تنظیم کرد. این متغیر به صورت PRODUCT_VIRTUAL_AB_COMPRESSION_FACTOR := 262144 تنظیم می‌شود.
  • استفاده از فشرده‌سازی مجدد پافین ، یک ابزار وصله‌گذاری قطعی برای جریان‌های deflate، که توابع فشرده‌سازی و diff را برای تولید به‌روزرسانی A/B OTA مدیریت می‌کند.
  • تغییرات در استفاده از ابزار تولید دلتا، مانند نحوه استفاده از کتابخانه bsdiff برای فشرده‌سازی پچ‌ها. در اندروید ۹ و بالاتر، ابزار bsdiff الگوریتم فشرده‌سازی را انتخاب می‌کند که بهترین نتایج فشرده‌سازی را برای یک پچ ارائه می‌دهد.
  • بهبودهای update_engine منجر به مصرف کمتر حافظه هنگام اعمال وصله‌ها برای به‌روزرسانی‌های دستگاه A/B شد.

بخش‌های بعدی به بررسی مسائل مختلفی که بر اندازه به‌روزرسانی‌های OTA تأثیر می‌گذارند، راه‌حل‌های آنها و نمونه‌هایی از پیاده‌سازی در AOSP می‌پردازند.

سفارش فایل

مشکل : سیستم‌های فایل، ترتیب فایل‌ها را هنگام درخواست لیستی از فایل‌های یک دایرکتوری تضمین نمی‌کنند، اگرچه معمولاً برای یک بررسی یکسان، ترتیب فایل‌ها یکسان است. ابزارهایی مانند ls به طور پیش‌فرض نتایج را مرتب می‌کنند، اما تابع wildcard که توسط دستوراتی مانند find و make استفاده می‌شود، مرتب‌سازی نمی‌کند. قبل از استفاده از این ابزارها، باید خروجی‌ها را مرتب کنید.

راه حل : وقتی از ابزارهایی مانند find و make به همراه تابع wildcard استفاده می‌کنید، قبل از استفاده از این دستورات، خروجی آنها را مرتب کنید. هنگام استفاده از $(wildcard) یا $(shell find) در فایل‌های Android.mk ، آنها را نیز مرتب کنید. برخی ابزارها، مانند جاوا، ورودی‌ها را مرتب می‌کنند، بنابراین قبل از مرتب‌سازی فایل‌ها، مطمئن شوید که ابزاری که استفاده می‌کنید قبلاً این کار را انجام نداده باشد.

مثال‌ها: بسیاری از موارد در سیستم ساخت اصلی با استفاده از ماکروی داخلی all-*-files-under که شامل all-cpp-files-under نیز می‌شود، اصلاح شدند (زیرا چندین تعریف در سایر makefileها پخش شده بودند). برای جزئیات بیشتر، به موارد زیر مراجعه کنید:

ساخت دایرکتوری

مشکل: تغییر دایرکتوری که برنامه‌ها در آن ساخته می‌شوند می‌تواند باعث شود فایل‌های باینری متفاوت باشند. اکثر مسیرها در ساخت اندروید، مسیرهای نسبی هستند، بنابراین __FILE__ در C/C++ مشکلی ایجاد نمی‌کند. با این حال، نمادهای اشکال‌زدایی به طور پیش‌فرض نام مسیر کامل را رمزگذاری می‌کنند و .note.gnu.build-id از هش کردن فایل‌های باینری از پیش حذف شده تولید می‌شود، بنابراین اگر نمادهای اشکال‌زدایی تغییر کنند، تغییر خواهد کرد.

راه حل: AOSP اکنون مسیرهای اشکال زدایی را نسبی می‌کند. برای جزئیات بیشتر، به CL مراجعه کنید: https://android.googlesource.com/platform/build/+/6a66a887baadc9eb3d0d60e26f748b8453e27a02 .

مهرهای زمانی

مشکل: مهرهای زمانی در خروجی ساخت منجر به تغییرات غیرضروری فایل می‌شوند. این احتمالاً در مکان‌های زیر اتفاق می‌افتد:

  • ماکروهای __DATE__/__TIME__/__TIMESTAMP__ در کد C یا C++.
  • مهرهای زمانی تعبیه شده در بایگانی‌های مبتنی بر زیپ.

راه حل‌ها/مثال‌ها: برای حذف مهرهای زمانی از خروجی ساخت، از دستورالعمل‌های داده شده در زیر در __DATE__/__TIME__/__TIMESTAMP__ در C/C++ و مهرهای زمانی تعبیه شده در archives استفاده کنید.

تابع __DATE__/__TIME__/__TIMESTAMP__ در زبان برنامه‌نویسی سی/سی‌پلاس‌پلاس

این ماکروها همیشه برای ساخت‌های مختلف، خروجی‌های متفاوتی تولید می‌کنند، بنابراین از آنها استفاده نکنید. در اینجا چند گزینه برای حذف این ماکروها آورده شده است:

مهرهای زمانی جاسازی‌شده در بایگانی‌ها (zip، jar)

اندروید ۷.۰ با اضافه کردن -X به تمام کاربردهای دستور zip ، مشکل برچسب‌های زمانی جاسازی‌شده در آرشیوهای zip را برطرف کرد. این کار UID/GID سازنده و برچسب زمانی یونیکس توسعه‌یافته را از فایل zip حذف کرد.

یک ابزار جدید، ziptime (واقع در /platform/build/+/android16-qpr1-release/tools/ziptime/ ) مهرهای زمانی معمول در هدرهای zip را بازنشانی می‌کند. برای جزئیات بیشتر، به فایل README مراجعه کنید.

ابزار signapk برای فایل‌های APK مهرهای زمانی تنظیم می‌کند که ممکن است بسته به منطقه زمانی سرور متفاوت باشد. برای جزئیات بیشتر، به CL مراجعه کنید https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028 .

ابزار signapk برای فایل‌های APK مهرهای زمانی تنظیم می‌کند که ممکن است بسته به منطقه زمانی سرور متفاوت باشد. برای جزئیات بیشتر، به CL مراجعه کنید https://android.googlesource.com/platform/build/+/6c41036bcf35fe39162b50d27533f0f3bfab3028 .

رشته‌های نسخه

مشکل: رشته‌های نسخه APK اغلب BUILD_NUMBER به نسخه‌های هاردکد شده خود اضافه می‌کردند. حتی اگر هیچ چیز دیگری در یک APK تغییر نمی‌کرد، در نتیجه، APK همچنان متفاوت می‌بود.

راه حل: شماره ساخت را از رشته نسخه APK حذف کنید.

مثال‌ها:

فعال کردن محاسبه‌ی صحت روی دستگاه

اگر dm-verity روی دستگاه شما فعال باشد، ابزارهای OTA به طور خودکار پیکربندی verity شما را دریافت کرده و محاسبات verity روی دستگاه را فعال می‌کنند. این امر به بلوک‌های verity اجازه می‌دهد تا به جای ذخیره شدن به صورت بایت‌های خام در بسته OTA شما، روی دستگاه‌های اندروید محاسبه شوند. بلوک‌های verity می‌توانند تقریباً ۱۶ مگابایت برای یک پارتیشن ۲ گیگابایتی استفاده کنند.

با این حال، محاسبه‌ی صحت روی دستگاه می‌تواند زمان زیادی طول بکشد. به طور خاص، کد تصحیح خطای رو به جلو می‌تواند زمان زیادی طول بکشد. در دستگاه‌های پیکسل، این کار معمولاً تا 10 دقیقه طول می‌کشد. در دستگاه‌های رده پایین می‌تواند بیشتر طول بکشد. اگر می‌خواهید محاسبه‌ی صحت روی دستگاه را غیرفعال کنید، اما همچنان dm-verity را فعال کنید، می‌توانید با ارسال --disable_fec_computation به ابزار ota_from_target_files هنگام ایجاد به‌روزرسانی OTA این کار را انجام دهید. این پرچم، محاسبه‌ی صحت روی دستگاه را در طول به‌روزرسانی‌های OTA غیرفعال می‌کند. این کار زمان نصب OTA را کاهش می‌دهد، اما اندازه‌ی بسته‌ی OTA را افزایش می‌دهد. اگر دستگاه شما dm-verity را فعال نکرده باشد، ارسال این پرچم هیچ تاثیری ندارد.

ابزارهای ساخت منسجم

مشکل: ابزارهایی که فایل‌های نصب‌شده تولید می‌کنند باید سازگار باشند (یک ورودی داده‌شده باید همیشه خروجی یکسانی تولید کند).

راه حل ها/مثال ها: تغییراتی در ابزارهای ساخت زیر مورد نیاز بود:

از ابزار build diff استفاده کنید

برای مواردی که حذف تغییرات فایل مربوط به ساخت امکان‌پذیر نیست، AOSP شامل یک ابزار تفاوت ساخت، target_files_diff.py برای استفاده در مقایسه دو بسته فایل است. این ابزار یک تفاوت بازگشتی بین دو ساخت انجام می‌دهد، به استثنای تغییرات رایج فایل مربوط به ساخت، مانند

  • تغییرات مورد انتظار در خروجی ساخت (برای مثال، به دلیل تغییر شماره ساخت).
  • تغییرات به دلیل مشکلات شناخته‌شده در سیستم ساخت فعلی.

برای استفاده از ابزار build diff، دستور زیر را اجرا کنید:

target_files_diff.py dir1 dir2

dir1 و dir2 دایرکتوری‌های پایه هستند که شامل فایل‌های هدف استخراج‌شده برای هر ساخت می‌باشند.

تخصیص بلوک را ثابت نگه دارید

برای یک فایل مشخص، اگرچه محتوای آن بین دو نسخه ثابت می‌ماند، اما بلوک‌های واقعی که داده‌ها را نگه می‌دارند ممکن است تغییر کرده باشند. در نتیجه، به‌روزرسانی‌کننده باید عملیات ورودی/خروجی غیرضروری را برای جابجایی بلوک‌ها جهت به‌روزرسانی OTA انجام دهد.

در یک به‌روزرسانی مجازی A/B OTA، ورودی/خروجی‌های غیرضروری می‌توانند فضای ذخیره‌سازی مورد نیاز برای ذخیره اسنپ‌شات کپی-هنگام-نوشتن را به میزان زیادی افزایش دهند. در یک به‌روزرسانی OTA غیر A/B، جابجایی بلوک‌ها برای به‌روزرسانی OTA به زمان به‌روزرسانی کمک می‌کند زیرا به دلیل جابجایی بلوک‌ها، ورودی/خروجی بیشتری وجود دارد.

برای رفع این مشکل، گوگل در اندروید ۷.۰ ابزار make_ext4fs را برای حفظ هماهنگی تخصیص بلوک در بین نسخه‌های مختلف توسعه داد. ابزار make_ext4fs یک پرچم اختیاری -d base_fs را می‌پذیرد که سعی می‌کند هنگام تولید یک تصویر ext4 ، فایل‌ها را به بلوک‌های مشابه اختصاص دهد. می‌توانید فایل‌های نگاشت بلوک (مانند فایل‌های نگاشت base_fs ) را از فایل زیپ فایل‌های هدف نسخه قبلی استخراج کنید. برای هر پارتیشن 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 را بهبود می‌بخشد. برای به‌روزرسانی‌های مجازی A/B، میزان فضای ذخیره‌سازی مورد نیاز برای اعمال OTA را به شدت کاهش می‌دهد.

از به‌روزرسانی برنامه‌ها خودداری کنید

علاوه بر به حداقل رساندن تفاوت‌های ساخت، می‌توانید با حذف به‌روزرسانی‌های برنامه‌هایی که از طریق فروشگاه‌های برنامه به‌روزرسانی می‌شوند، حجم به‌روزرسانی‌های OTA را کاهش دهید. فایل‌های APK اغلب بخش قابل توجهی از پارتیشن‌های مختلف دستگاه را تشکیل می‌دهند. گنجاندن آخرین نسخه‌های برنامه‌هایی که توسط فروشگاه‌های برنامه به‌روزرسانی می‌شوند در به‌روزرسانی OTA ممکن است تأثیر زیادی بر حجم بسته‌های OTA داشته باشد و سود کمی برای کاربر داشته باشد. زمانی که کاربران بسته OTA را دریافت می‌کنند، ممکن است برنامه به‌روزرسانی شده یا حتی نسخه جدیدتری را مستقیماً از فروشگاه‌های برنامه دریافت کرده باشند.