کاهش اندازه OTA

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

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

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

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

  • استفاده از Brotli ، یک الگوریتم فشرده سازی بدون تلفات با هدف عمومی برای تصاویر کامل در به روز رسانی دستگاه های غیر A/B. Brotli را می توان برای بهینه سازی فشرده سازی سفارشی کرد. در به‌روزرسانی‌های بزرگ‌تر که از دو یا چند بلوک در سیستم فایل تشکیل شده‌اند (مثلا system.img )، سازندگان یا شرکای دستگاه می‌توانند الگوریتم‌های فشرده‌سازی خود را اضافه کنند و می‌توانند از الگوریتم‌های فشرده‌سازی متفاوت در بلوک‌های مختلف همان به‌روزرسانی استفاده کنند.
  • استفاده از فشرده‌سازی مجدد Puffin ، یک ابزار اصلاحی قطعی برای تخلیه جریان‌ها، که عملکردهای فشرده‌سازی و تفاوت را برای تولید به‌روزرسانی A/B OTA انجام می‌دهد.
  • تغییراتی در استفاده از ابزار نسل دلتا، مانند نحوه استفاده از کتابخانه bsdiff برای فشرده‌سازی وصله‌ها. در اندروید 9 و بالاتر، ابزار bsdiff الگوریتم فشرده‌سازی را انتخاب می‌کند که بهترین نتایج فشرده‌سازی را برای یک پچ ارائه می‌دهد.
  • هنگامی که وصله‌ها برای به‌روزرسانی‌های دستگاه A/B اعمال می‌شوند، بهبودهایی در update_engine منجر به مصرف کمتر حافظه می‌شود.
  • بهبودهایی در تقسیم فایل های فشرده بزرگ برای به روز رسانی OTA مبتنی بر بلوک. یک حالت در imgdiff فایل‌های APK بزرگ را بر اساس نام ورودی تقسیم می‌کند. در مقایسه با تقسیم خطی فایل‌ها و استفاده از ابزار bsdiff برای فشرده‌سازی، پچ کوچک‌تری تولید می‌کند.

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

سفارش فایل

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

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

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

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

مشکل: تغییر دایرکتوری که در آن چیزها ساخته شده اند می تواند باعث متفاوت شدن باینری ها شود. بیشتر مسیرها در ساخت اندروید مسیرهای نسبی هستند، بنابراین __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++

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

مهرهای زمانی تعبیه شده در آرشیوها (زیپ، شیشه)

اندروید 7.0 با افزودن -X به همه کاربردهای دستور zip ، مشکل زمان‌بندی جاسازی شده در بایگانی‌های فشرده را برطرف کرد. با این کار UID/GID سازنده و مُهر زمانی Unix توسعه یافته از فایل فشرده حذف شد.

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

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

رشته های نسخه

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

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

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

مثال ها:

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

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

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

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

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

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

با استفاده از ابزار build diff

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

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

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

target_files_diff.py dir1 dir2

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

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

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

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

برای رفع این مشکل، گوگل در اندروید 7.0 ابزار 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 کمک نمی کند، اما با کاهش مقدار I/O، عملکرد به روز رسانی OTA را بهبود می بخشد. برای به‌روزرسانی‌های A/B مجازی، فضای ذخیره‌سازی مورد نیاز برای اعمال OTA را به شدت کاهش می‌دهد.

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

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