آیا Google از A/B OTA در هر دستگاهی استفاده کرده است؟
آره. نام بازاریابی بهروزرسانیهای A/B بهروزرسانیهای بدون درز است. تلفنهای Pixel و Pixel XL از اکتبر ۲۰۱۶ با A/B عرضه میشوند، و همه Chromebookها از یک اجرای update_engine
A/B استفاده میکنند. اجرای کد پلت فرم لازم در اندروید 7.1 و بالاتر عمومی است.
چرا A/B OTA بهتر هستند؟
A/B OTA تجربه کاربری بهتری را هنگام دریافت بهروزرسانی ارائه میکند. اندازهگیریهای بهروزرسانیهای امنیتی ماهانه نشان میدهد که این ویژگی قبلاً موفقیتآمیز بوده است: از ماه می ۲۰۱۷، ۹۵ درصد از دارندگان پیکسل در مقایسه با ۸۷ درصد از کاربران Nexus، آخرین بهروزرسانی امنیتی را پس از یک ماه اجرا میکنند، و کاربران Pixel زودتر از کاربران Nexus بهروزرسانی میشوند. عدم بهروزرسانی بلوکها در طول OTA دیگر منجر به بوت نشدن دستگاه نمیشود. تا زمانی که تصویر سیستم جدید با موفقیت بوت نشود، اندروید توانایی بازگشت به تصویر قبلی سیستم را حفظ می کند.
system_other چیست؟
برنامه ها در فایل های apk. که در واقع آرشیو ZIP هستند، ذخیره می شوند. هر فایل apk. داخل خود یک یا چند فایل .dex حاوی بایت کد دالویک قابل حمل دارد. یک فایل odex. (dex. بهینه شده) جدا از فایل apk. زندگی می کند و می تواند حاوی کد ماشین مخصوص دستگاه باشد. اگر یک فایل odex در دسترس باشد، Android میتواند برنامهها را با سرعت کامپایلشده زودتر اجرا کند، بدون اینکه هر بار که برنامه اجرا میشود منتظر کامپایل شدن کد باشد. یک فایل odex کاملاً ضروری نیست: Android در واقع میتواند کد .dex را مستقیماً از طریق تفسیر یا کامپایل Just-In-Time (JIT) اجرا کند، اما یک فایل odex بهترین ترکیب سرعت راهاندازی و سرعت زمان اجرا را فراهم میکند. فضا در دسترس است
مثال: برای installed-files.txt از Nexus 6P دارای Android 7.1 با حجم کلی تصویر سیستم 2628 MiB (2755792836 بایت)، تفکیک بزرگترین مشارکت کنندگان در اندازه کلی تصویر سیستم بر اساس نوع فایل به شرح زیر است:
.odex | 1391770312 بایت | 50.5٪ |
apk | 846878259 بایت | 30.7٪ |
.so (کد اصلی C/C++) | 202162479 بایت | 7.3٪ |
فایل های جو دوسر / تصاویر هنری | 163892188 بایت | 5.9٪ |
فونت ها | 38952361 بایت | 1.4٪ |
داده های محلی icu | 27468687 بایت | 0.9٪ |
این ارقام برای دستگاههای دیگر نیز مشابه است، بنابراین در دستگاههای 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 The Evolution of Art مراجعه کنید.
مقایسه به چند دلیل کلیدی دشوار است:
- برنامههای بهروزرسانیشده توسط Google Play همیشه فایلهای odex خود را به محض دریافت اولین بهروزرسانی روی
/data
دارند. - برنامه هایی که کاربر اجرا نمی کند به هیچ وجه به فایل odex. نیاز ندارند.
- کامپایل مبتنی بر نمایه، فایلهای odex. کوچکتری را نسبت به کامپایلهای زودهنگام تولید میکند (زیرا اولی فقط کدهای حیاتی عملکرد را بهینه میکند).
برای جزئیات بیشتر در مورد گزینه های تنظیم موجود برای OEM ها، به پیکربندی ART مراجعه کنید.
آیا دو کپی از فایل های .odex در /data وجود ندارد؟
کمی پیچیدهتر است... پس از نوشتن تصویر سیستم جدید، نسخه جدید dex2oat در برابر فایلهای .dex جدید اجرا میشود تا فایلهای .odex جدید تولید شوند. این در حالی رخ میدهد که سیستم قدیمی هنوز در حال اجرا است، بنابراین فایلهای قدیمی و جدید odex. هر دو همزمان روی /data
هستند.
کد موجود در OtaDexoptService ( frameworks/base/+/main/services/core/java/com/android/server/pm/OtaDexoptService.java
) قبل از بهینهسازی هر بسته، getAvailableSpace
فراخوانی میکند تا از پر کردن بیش از حد /data
جلوگیری شود. توجه داشته باشید که موجود در اینجا هنوز محافظه کارانه است: این مقدار فضای باقی مانده قبل از رسیدن به آستانه فضای کم معمولی سیستم (که هم به صورت درصد و هم به عنوان تعداد بایت اندازه گیری می شود) است. بنابراین اگر /data
پر باشد، دو کپی از هر فایل odex وجود نخواهد داشت. همین کد یک BULK_DELETE_THRESHOLD نیز دارد: اگر دستگاه به پر کردن فضای موجود نزدیک شود (همانطور که توضیح داده شد)، فایلهای odex. متعلق به برنامههایی که استفاده نمیشوند حذف میشوند. این یک مورد دیگر بدون دو کپی از هر فایل odex است.
در بدترین حالت که /data
کاملاً پر است، به روز رسانی منتظر می ماند تا دستگاه به سیستم جدید راه اندازی شود و دیگر نیازی به فایل های odex سیستم قدیمی ندارد. PackageManager این موارد را انجام می دهد: ( frameworks/base/+/main/services/core/java/com/android/server/pm/PackageManagerService.java#7215
). پس از راهاندازی موفقیتآمیز سیستم جدید، installd
( frameworks/native/+/main/cmds/installd/dexopt.cpp#2422
) میتواند فایلهای .odex را که توسط سیستم قدیمی استفاده میشد حذف کند و دستگاه را به حالت ثابت بازگرداند. جایی که فقط یک کپی وجود دارد
بنابراین، در حالی که ممکن است /data
شامل دو کپی از همه فایلهای odex باشد، (الف) این موقتی است و (ب) تنها در صورتی اتفاق میافتد که به هر حال فضای خالی زیادی روی /data
داشته باشید. به جز در هنگام به روز رسانی، تنها یک نسخه وجود دارد. و بهعنوان بخشی از ویژگیهای استحکام عمومی ART، هرگز /data
با فایلهای odex. پر نمیکند (زیرا در سیستمهای غیر A/B نیز مشکل ایجاد میشود).
آیا این همه نوشتن/کپی باعث افزایش سایش فلاش نمی شود؟
فقط بخش کوچکی از فلاش بازنویسی میشود: بهروزرسانی کامل سیستم پیکسل حدود 2.3 گیگابایت مینویسد. (برنامه ها نیز دوباره کامپایل می شوند، اما این در مورد غیر A/B نیز صادق است.) به طور سنتی، OTAهای کامل مبتنی بر بلوک، مقدار مشابهی از داده را می نوشتند، بنابراین نرخ سایش فلاش باید مشابه باشد.
آیا فلش دو پارتیشن سیستم باعث افزایش زمان فلش کارخانه می شود؟
خیر. پیکسل اندازه تصویر سیستم را افزایش نداد (فقط فضا را بین دو پارتیشن تقسیم کرد).
آیا نگه داشتن فایلهای odex روی B باعث کندی راهاندازی مجدد پس از تنظیم مجدد دادههای کارخانه نمیشود؟
آره. اگر واقعاً از دستگاهی استفاده کردهاید، OTA گرفتهاید و بازنشانی دادههای کارخانه را انجام دادهاید، اولین راهاندازی مجدد کندتر از حالت قبلی خواهد بود (1m40s در مقابل 40s در Pixel XL) زیرا فایلهای odex. B بعد از اولین OTA و بنابراین نمی توان در /data
کپی کرد. این مبادله است.
بازنشانی داده های کارخانه در مقایسه با بوت معمولی باید یک عملیات نادر باشد، بنابراین زمان صرف شده اهمیت کمتری دارد. (این روی کاربران یا بازبینانی که دستگاه خود را از کارخانه دریافت می کنند تأثیر نمی گذارد، زیرا در این صورت پارتیشن B در دسترس است.) استفاده از کامپایلر JIT به این معنی است که ما نیازی به کامپایل مجدد همه چیز نداریم، بنابراین به اندازه شما بد نیست. ممکن است فکر کند همچنین میتوان با استفاده از coreApp="true"
در مانیفست، برنامهها را بهعنوان نیاز به کامپایل زودرس علامتگذاری کرد: ( frameworks/base/+/main/packages/SystemUI/AndroidManifest.xml#23
). این در حال حاضر توسط system_server
استفاده می شود زیرا به دلایل امنیتی مجاز به JIT نیست.
آیا نگه داشتن فایلهای odex روی /data به جای سیستم / باعث راهاندازی مجدد پس از OTA کند نمیشود؟
خیر. همانطور که در بالا توضیح داده شد، dex2oat جدید در حالی اجرا میشود که تصویر سیستم قدیمی هنوز در حال اجرا است تا فایلهای مورد نیاز سیستم جدید تولید شود. بهروزرسانی تا زمانی که کار انجام نشده باشد، در دسترس نیست.
آیا (باید) دستگاه A/B 32 گیگا بایتی ارسال کنیم؟ 16 گیگابایت؟ 8 گیگابایت؟
32 گیگا بایت همانطور که در پیکسل ثابت شده است به خوبی کار می کند و 320 مگابایت از 16 گیگابایت به معنای کاهش 2 درصدی است. به طور مشابه، 320 مگابایت از 8 گیگابایت کاهش 4٪. بدیهی است که A/B انتخاب پیشنهادی برای دستگاههای با 4 گیگابایت نیست، زیرا 320 مگابایت سربار تقریباً 10 درصد از کل فضای موجود را تشکیل میدهد.
آیا AVB2.0 به A/B OTA نیاز دارد؟
خیر. Android Verified Boot همیشه به بهروزرسانیهای مبتنی بر بلوک نیاز داشته است، اما نه لزوماً بهروزرسانی A/B.
آیا A/B OTA به AVB2.0 نیاز دارد؟
خیر
آیا A/B OTA محافظ برگشتی AVB2.0 را می شکند؟
خیر. در اینجا مقداری سردرگمی وجود دارد زیرا اگر یک سیستم A/B نتواند در تصویر سیستم جدید بوت شود (پس از چند بار تلاش مجدد که بوت لودر شما تعیین می کند) به طور خودکار به تصویر سیستم "قبلی" برمی گردد. نکته کلیدی در اینجا این است که "قبلی" در معنای A/B در واقع هنوز تصویر سیستم "جاری" است. به محض اینکه دستگاه با موفقیت یک تصویر جدید را بوت کرد، محافظت برگشتی فعال می شود و تضمین می کند که نمی توانید به عقب برگردید. اما تا زمانی که واقعاً تصویر جدید را با موفقیت بوت نکرده باشید، حفاظت از عقبگرد آن را تصویر فعلی سیستم در نظر نمی گیرد.
اگر در حال نصب یک به روز رسانی در حالی که سیستم در حال اجرا است، کند نیست؟
با بهروزرسانیهای غیر A/B، هدف نصب بهروزرسانی در سریعترین زمان ممکن است زیرا کاربر منتظر است و نمیتواند از دستگاه خود در حین اعمال بهروزرسانی استفاده کند. با بهروزرسانیهای A/B، برعکس این موضوع صادق است. از آنجایی که کاربر هنوز از دستگاه خود استفاده می کند، هدف تا حد ممکن کمترین تأثیر است، بنابراین به روز رسانی عمدا کند است. از طریق منطق در کلاینت بهروزرسانی سیستم جاوا (که برای Google GmsCore است، بسته اصلی ارائهشده توسط GMS)، اندروید همچنین سعی میکند زمانی را انتخاب کند که کاربران اصلاً از دستگاههای خود استفاده نمیکنند. این پلتفرم از توقف/ازسرگیری بهروزرسانی پشتیبانی میکند، و در صورتی که کاربر شروع به استفاده از دستگاه کند، مشتری میتواند از آن برای توقف بهروزرسانی استفاده کند و وقتی دستگاه دوباره بیحرکت است، آن را از سر بگیرد.
هنگام گرفتن OTA دو مرحله وجود دارد که به وضوح در UI به عنوان مرحله 1 از 2 و مرحله 2 از 2 در زیر نوار پیشرفت نشان داده شده است. مرحله 1 با نوشتن بلوک های داده مطابقت دارد، در حالی که مرحله 2 پیش کامپایل کردن فایل های .dex است. این دو فاز از نظر تأثیر عملکرد کاملاً متفاوت هستند. فاز اول I/O ساده است. این به منابع کمی نیاز دارد (RAM، CPU، I/O) زیرا فقط به آرامی بلوک ها را در اطراف کپی می کند.
فاز دوم dex2oat را اجرا می کند تا تصویر سیستم جدید را از پیش کامپایل کند. این بدیهی است که محدودیت های کمتری در مورد نیازهای خود دارد زیرا برنامه های واقعی را کامپایل می کند. و بدیهی است که کار بسیار بیشتری در کامپایل یک برنامه بزرگ و پیچیده نسبت به یک برنامه کوچک و ساده وجود دارد. در حالی که در فاز 1 هیچ بلوک دیسکی بزرگتر یا پیچیده تر از بقیه وجود ندارد.
این روند مشابه زمانی است که Google Play یک بهروزرسانی برنامه را قبل از نمایش اعلان بهروزرسانی شده 5 برنامه در پسزمینه نصب میکند، همانطور که برای سالها انجام شده است.
اگر کاربر واقعاً منتظر به روز رسانی باشد چه؟
اجرای فعلی در GmsCore بین بهروزرسانیهای پسزمینه و بهروزرسانیهای آغاز شده توسط کاربر تمایزی قائل نمیشود، اما ممکن است در آینده این کار را انجام دهد. در مواردی که کاربر صراحتاً درخواست نصب بهروزرسانی را کرده است یا در حال تماشای صفحه پیشرفت بهروزرسانی است، با این فرض که آنها فعالانه منتظر اتمام آن هستند، کار بهروزرسانی را در اولویت قرار میدهیم.
در صورت عدم اعمال به روز رسانی چه اتفاقی می افتد؟
در بهروزرسانیهای غیر A/B، اگر یک بهروزرسانی اعمال نمیشد، معمولاً یک دستگاه غیرقابل استفاده برای کاربر باقی میماند. تنها استثنا در صورتی بود که خرابی قبل از شروع برنامه اتفاق بیفتد (مثلاً چون بسته نتوانست تأیید کند). با بهروزرسانیهای A/B، عدم اعمال بهروزرسانی بر سیستم در حال اجرا تأثیری نمیگذارد. بهروزرسانی را میتوان بعداً دوباره امتحان کرد.