آیا Google از بهروزرسانیهای بیسیم A/B در دستگاهی استفاده کرده است؟
بله. نام بازاریابی برای بهروزرسانیهای A/B، بهروزرسانیهای یکپارچه است. تلفنهای Pixel و Pixel XL از اکتبر ۲۰۱۶ با A/B عرضه شدند و همه Chromebookها از همان پیادهسازی A/B استفاده میکنند.update_engine پیادهسازی کد پلاتفرم لازم در Android 7.1 و
بالاتر عمومی است.
چرا بهروزرسانیهای بیسیم A/B بهتر هستند؟
«بهروزرسانیهای از راه دور A/B» هنگام دریافت بهروزرسانیها تجربه کاربری بهتری ارائه میدهد. اندازهگیریهای بهروزرسانیهای امنیتی ماهانه نشان میدهد که این ویژگی ازقبل موفقیت خود را ثابت کرده است: از ماه مه ۲۰۱۷، ۹۵٪ از مالکان Pixel پساز یک ماه از جدیدترین بهروزرسانی امنیتی استفاده میکنند، درحالیکه این رقم برای کاربران Nexus ۸۷٪ است، و کاربران Pixel زودتر از کاربران Nexus بهروزرسانی میکنند. اگر بهروزرسانی بلوکها درطول «بهروزرسانی از راه دور» ناموفق باشد، دیگر دستگاهی که بوت نمیشود نتیجه نخواهد داد؛ تا زمانی که تصویر سیستم جدید با موفقیت بوت شود، Android قابلیت بازگشت به تصویر سیستم کاری قبلی را حفظ میکند.
system_other چیست؟
برنامهها در فایلهای .apk ذخیره میشوند که درواقع بایگانیهای ZIP هستند. هر فایل .apk حاوی یک یا چند فایل .dex است که حاوی بایتکد قابلحمل Dalvik است. فایل .odex (بهینهسازیشده .dex) جدا از فایل .apk قرار دارد و میتواند حاوی کد ماشین مختص دستگاه باشد. اگر فایل odex دردسترس باشد، Android میتواند برنامهها را با سرعتهای کامپایل پیشاز زمان اجرا کند بدون اینکه لازم باشد هر بار که برنامه راهاندازی میشود منتظر کامپایل کد بماند. فایل .odex کاملاً ضروری نیست: Android درواقع میتواند کد .dex را مستقیماً ازطریق تفسیر یا ترجمه همزمان (JIT) اجرا کند، اما اگر فضا دردسترس باشد، فایل .odex بهترین ترکیب سرعت راهاندازی و سرعت زمان اجرا را ارائه میدهد.
مثال: برای installed-files.txt از Nexus 6P با Android 7.1 و اندازه کل تصویر سیستم ۲۶۲۸ مگابایت (۲۷۵۵۷۹۲۸۳۶ بایت)، تفکیک بزرگترین مشارکتکنندگان در اندازه کلی تصویر سیستم براساس نوع فایل بهصورت زیر است:
| .odex | ۱۳۹۱۷۷۰۳۱۲ بایت | ٪۵۰٫۵ |
| .apk | ۸۴۶۸۷۸۲۵۹ بایت | ٪۳۰٫۷ |
| .so (کد C/C++ بومی) | ۲۰۲۱۶۲۴۷۹ بایت | ٪۷٫۳ |
| فایلهای oat./تصاویر art. | 163892188 bytes | ۵٫۹٪ |
| قلم | 38952361 bytes | ٪۱٫۴ |
| دادههای منطقه زبانی icu | ۲۷۴۶۸۶۸۷ بایت | ٪۰٫۹ |
این ارقام برای دستگاههای دیگر نیز مشابه است، بنابراین در دستگاههای Nexus/Pixel، فایلهای odex تقریباً نیمی از پارتیشن سیستم را اشغال میکنند. این یعنی میتوانستیم همچنان از ext4 استفاده کنیم اما فایلهای odex .را در کارخانه در پارتیشن B بنویسیم و سپس آنها را در اولین راهاندازی در /data کپی کنیم. فضای ذخیرهسازی واقعی استفادهشده با ext4 A/B با SquashFS A/B یکسان است، زیرا اگر از SquashFS استفاده کرده بودیم، فایلهای .odex پیشبهینهشده را بهجای system_b در system_a ارسال میکردیم.
آیا کپی کردن فایلهای odex .در data /به این معنی نیست که فضای ذخیرهشده در system /در data /ازدست میرود؟
نه دقیقاً. در Pixel، بیشتر فضای اشغالشده توسط فایلهای odex مربوط به برنامهها است که معمولاً در /data وجود دارند. این برنامهها بهروزرسانیهای Google Play را دریافت میکنند، بنابراین فایلهای .apk و .odex
در تصویر سیستم برای بیشتر عمر دستگاه استفاده نمیشوند. چنین فایلهایی میتوانند بهطور کامل کنار گذاشته شوند و وقتی کاربر واقعاً از هر برنامه استفاده میکند، با فایلهای .odex کوچک و مبتنی بر نمایه جایگزین شوند (بنابراین برای برنامههایی که کاربر استفاده نمیکند فضایی لازم نیست). برای جزئیات، به سخنرانی Google I/O 2016 با عنوان تکامل هنر مراجعه کنید.
مقایسه بهچند دلیل کلیدی دشوار است:
-
برنامههایی که Google Play بهروزرسانی میکند همیشه فایلهای .odex خود را در
/dataبهمحض دریافت اولین بهروزرسانی دارند. - برنامههایی که کاربر اجرا نمیکند اصلاً به فایل odex .نیاز ندارند.
- کامپایل مبتنی بر نمایه فایلهای odex .کوچکتری نسبت به کامپایل پیشاز موعد تولید میکند (زیرا کامپایل مبتنی بر نمایه فقط کد حیاتی برای عملکرد را بهینهسازی میکند).
برای جزئیات مربوط به گزینههای تنظیم دردسترس برای OEM، به پیکربندی ART مراجعه کنید.
آیا دو نسخه از فایلهای .odex در /data وجود ندارد؟
کمی پیچیدهتر است… پساز اینکه تصویر سیستم جدید نوشته شد، نسخه جدید dex2oat روی فایلهای .dex جدید اجرا میشود تا فایلهای .odex جدید تولید شود. این
اتفاق درحالی رخ میدهد که سیستم قدیمی هنوز درحال اجرا است، بنابراین فایلهای .odex قدیمی و جدید هر دو بهطور همزمان در
/data قرار دارند.
کد موجود در OtaDexoptService (frameworks/base/+/android17-release/services/core/java/com/android/server/pm/OtaDexoptService.java) قبلاز بهینهسازی هر بسته، getAvailableSpace را فرا میخواند تا از پر شدن بیشازحد
/data جلوگیری کند. توجه داشته باشید که فضای دردسترس در اینجا همچنان محافظهکارانه است: این مقدار فضای باقیمانده قبلاز رسیدن به آستانه معمول فضای کم سیستم است (که هم بهصورت درصد و هم بهصورت تعداد بایت اندازهگیری میشود). بنابراین اگر /data پر باشد، دو نسخه از
هر فایل .odex وجود نخواهد داشت. همین کد دارای BULK_DELETE_THRESHOLD نیز هست: اگر دستگاه به پر شدن فضای دردسترس (همانطور که در بالا توضیح داده شد) نزدیک شود، فایلهای .odex متعلق به برنامههایی که استفاده نمیشوند برداشته میشوند. این مورد دیگری است که در آن دو نسخه از هر فایل .odex وجود ندارد.
در بدترین حالت که /data کاملاً پر است، بهروزرسانی تا زمانی که دستگاه در سیستم جدید بازراهاندازی شود و دیگر به فایلهای odex .سیستم قدیمی نیاز نداشته باشد منتظر میماند.
PackageManager این کار را انجام میدهد: (frameworks/base/+/android17-release/services/core/java/com/android/server/pm/PackageManagerService.java#7215). پساز اینکه سیستم جدید باموفقیت راهاندازی شد، installd (frameworks/native/+/android17-release/cmds/installd/dexopt.cpp#2422) میتواند فایلهای .odex را که سیستم قدیمی استفاده میکرد بردارد و دستگاه را به حالت پایدار برگرداند که فقط یک نسخه وجود دارد.
بنابراین، اگرچه ممکن است /data حاوی دو نسخه از همه فایلهای odex .باشد،
(الف) این موقتی است و (ب) فقط درصورتی اتفاق میافتد که بههرحال فضای خالی زیادی در
/data داشته باشید. بهجز درطول بهروزرسانی، فقط یک نسخه وجود دارد. و بهعنوان بخشی از
ویژگیهای کلی استحکام ART، هرگز /data را با فایلهای .odex پر نخواهد کرد (زیرا این کار در سیستم غیر A/B نیز مشکلساز خواهد بود).
آیا این همه نوشتن/کپی کردن باعث افزایش فرسودگی فلش نمیشود؟
فقط بخش کوچکی از حافظه فلش بازنویسی میشود: بهروزرسانی کامل سیستم Pixel حدود ۲٫۳ گیگابایت مینویسد. (برنامهها نیز دوباره کامپایل میشوند، اما این موضوع برای آزمایشهای غیر A/B نیز صادق است.) بهطور سنتی، OTAهای کامل مبتنی بر بلوک مقدار مشابهی از دادهها را مینویسند، بنابراین نرخهای فرسودگی فلش باید مشابه باشد.
آیا چشمک زدن دو پارتیشن سیستم زمان چشمک زدن کارخانهای را افزایش میدهد؟
نه. اندازه تصویر سیستم Pixel افزایش نیافته است (فقط فضا را بین دو پارتیشن تقسیم کرده است).
آیا نگه داشتن فایلهای .odex در B باعث نمیشود راهاندازی مجدد پساز بازنشانی دادههای کارخانه کند شود؟
بله. اگر واقعاً از دستگاهی استفاده کردهاید، «بهروزرسانی ازطریق شبکه» دریافت کردهاید، و بازنشانی کارخانهای انجام دادهاید،
اولین راهاندازی مجدد کندتر از حالت عادی خواهد بود (۱ دقیقه و ۴۰ ثانیه دربرابر ۴۰ ثانیه در Pixel XL) زیرا
فایلهای odex پساز اولین «بهروزرسانی ازطریق شبکه» در B ازدست رفتهاند و بنابراین نمیتوانند در
/data کپی شوند. این معامله است.
بازنشانی دادههای کارخانه در مقایسه با راهاندازی معمولی باید بهندرت انجام شود، بنابراین زمان صرفشده
اهمیت کمتری دارد. (این موضوع بر کاربران یا بازبینانی که دستگاهشان را از کارخانه دریافت میکنند تأثیری ندارد، زیرا در این حالت پارتیشن B دردسترس است.) استفاده از گردآورنده JIT به این معنی است که ما
نیازی به بازگردآوری همه چیز نداریم، بنابراین به بدی آنچه فکر میکنید نیست. همچنین میتوان بااستفاده از
coreApp="true" در مانیفست، برنامهها را بهعنوان برنامههایی که به
ترجمه پیشاززمان نیاز دارند علامتگذاری کرد: (frameworks/base/+/android17-release/packages/SystemUI/AndroidManifest.xml#23). درحالحاضر system_server از این ویژگی استفاده میکند زیرا به دلایل امنیتی اجازه ندارد از ترجمه همزمان استفاده کند.
آیا نگه داشتن فایلهای odex .در data /بهجای system /باعث نمیشود بازراهاندازی پساز OTA کند شود؟
خیر. همانطور که در بالا توضیح داده شد، dex2oat جدید درحالی اجرا میشود که تصویر سیستم قدیمی هنوز درحال اجرا است تا فایلهایی را که سیستم جدید به آنها نیاز دارد تولید کند. تا زمانی که این کار انجام نشود، بهروزرسانی دردسترس درنظر گرفته نمیشود.
آیا میتوانیم (باید) دستگاه A/B با ۳۲ گیگابایت حافظه داخلی عرضه کنیم؟ ۱۶ گیگابایت؟ ۸ گیبیبایت؟
۳۲ گیگابایت بهخوبی کار میکند، زیرا در Pixel ثابت شده است، و ۳۲۰ مگابایت از ۱۶ گیگابایت یعنی کاهش ۲٪. بههمین ترتیب، ۳۲۰ مگابایت از ۸ گیگابایت، ۴٪ کاهش. بدیهی است که A/B انتخاب توصیهشده در دستگاههای دارای ۴ گیگابایت نخواهد بود، زیرا سربار ۳۲۰ مبیبایت تقریباً ۱۰٪ از کل فضای دردسترس است.
آیا AVB2.0 به OTAهای A/B نیاز دارد؟
نه. راهاندازی تأییدشده Android همیشه به بهروزرسانیهای مبتنی بر بلوک نیاز داشته است، اما لزوماً به بهروزرسانیهای A/B نیاز نداشته است.
آیا OTAهای A/B به AVB2.0 نیاز دارند؟
شماره.
آیا OTAهای A/B محافظت بازگشت AVB2.0 را میشکنند؟
نه. در اینجا کمی ابهام وجود دارد زیرا اگر سیستم A/B نتواند در تصویر سیستم جدید راهاندازی شود، (پساز چند بار تلاش مجدد که توسط بوتلودر شما تعیین میشود) بهطور خودکار به تصویر سیستم «قبلی» برمیگردد. نکته کلیدی در اینجا این است که «قبلی» در مفهوم A/B درواقع همچنان تصویر سیستم «فعلی» است. بهمحض اینکه دستگاه با موفقیت تصویر جدیدی را راهاندازی کند، محافظت دربرابر بازگشت به نسخه قبلی فعال میشود و تضمین میکند که نمیتوانید به نسخه قبلی برگردید. اما تا زمانی که تصویر جدید را با موفقیت راهاندازی نکردهاید، محافظت دربرابر بازگرداندن آن را بهعنوان تصویر سیستم فعلی درنظر نمیگیرد.
اگر درحالیکه سیستم درحال اجرا است بهروزرسانی نصب کنید، این کار کند نیست؟
هدف از بهروزرسانیهای غیر A/B این است که بهروزرسانی در سریعترین زمان ممکن نصب شود زیرا کاربر منتظر است و درحین اعمال بهروزرسانی نمیتواند از دستگاهش استفاده کند. در بهروزرسانیهای A/B، برعکس این موضوع صادق است؛ چون کاربر همچنان از دستگاهش استفاده میکند، هدف این است که بهروزرسانی کمترین تأثیر ممکن را داشته باشد، بنابراین بهروزرسانی بهطور عمدی کند است. ازطریق منطق در مشتری بهروزرسانی سیستم Java (که برای Google، GmsCore، بسته اصلی ارائهشده توسط GMS است)، Android همچنین تلاش میکند زمانی را انتخاب کند که کاربران اصلاً از دستگاههایشان استفاده نمیکنند. این پلاتفرم از توقف موقت/ازسرگیری بهروزرسانی پشتیبانی میکند و کارخواه میتواند از آن برای توقف موقت بهروزرسانی استفاده کند، اگر کاربر شروع به استفاده از دستگاه کند و آن را دوباره زمانی که دستگاه غیرفعال است ازسر بگیرد.
هنگام دریافت OTA، دو مرحله وجود دارد که بهوضوح در رابط کاربری بهعنوان مرحله ۱ از ۲ و مرحله ۲ از ۲ زیر نوار پیشرفت نشان داده میشود. مرحله ۱ مربوط به نوشتن بلوکهای داده است، درحالیکه مرحله ۲ مربوط به پیشکامپایل کردن فایلهای dex .است. این دو مرحله ازنظر تأثیر بر عملکرد بسیار متفاوت هستند. مرحله اول ورودی/خروجی ساده است. این کار به منابع (RAM، CPU، I/O) کمی نیاز دارد زیرا فقط بلوکها را بهآرامی کپی میکند.
فاز دوم dex2oat را اجرا میکند تا تصویر سیستم جدید را ازپیش کامپایل کند. این مورد بهدلیل اینکه برنامههای واقعی را گردآوری میکند، بهوضوح محدودیتهای کمتری در الزامات خود دارد. و بدیهی است که کار بسیار بیشتری برای کامپایل کردن یک برنامه بزرگ و پیچیده نسبت به یک برنامه کوچک و ساده لازم است؛ درحالیکه در فاز ۱ هیچ بلوک دیسکی وجود ندارد که بزرگتر یا پیچیدهتر از بقیه باشد.
این فرایند مشابه زمانی است که Google Play بهروزرسانی برنامه را در پسزمینه نصب میکند و سپس اعلان ۵ برنامه بهروز شد را نمایش میدهد، همانطور که سالها است انجام میشود.
اگر کاربری واقعاً منتظر بهروزرسانی باشد چه؟
پیادهسازی فعلی در GmsCore بین بهروزرسانیهای پسزمینهای و بهروزرسانیهای کاربر-شروعشده تمایز قائل نمیشود اما ممکن است در آینده این کار را انجام دهد. در مواردی که کاربر صریحاً درخواست کرده است که بهروزرسانی نصب شود یا درحال تماشای صفحه پیشرفت بهروزرسانی است، کار بهروزرسانی را با این فرض که کاربر فعالانه منتظر اتمام آن است در اولویت قرار میدهیم.
اگر بهروزرسانی اعمال نشود چه اتفاقی میافتد؟
در بهروزرسانیهای غیر A/B، اگر بهروزرسانی اعمال نمیشد، معمولاً دستگاه کاربر غیرقابل استفاده میشد. تنها استثنا زمانی بود که خرابی قبلاز شروع برنامه رخ میداد (مثلاً بهدلیل عدم تأیید بسته). با بهروزرسانیهای A/B، اعمال نشدن بهروزرسانی بر سیستم درحال اجرا تأثیر نمیگذارد. بهروزرسانی را میتوان بعداً دوباره امتحان کرد.