تولیدکنندگان اصلی تجهیزات (OEM) و فروشندگان SoC که میخواهند بهروزرسانیهای سیستم A/B را پیادهسازی کنند، باید مطمئن شوند که بوتلودر آنها boot_control HAL را پیادهسازی کرده و پارامترهای صحیح را به هسته منتقل میکند.
پیادهسازی کنترل بوت HAL
بوت لودرهای دارای قابلیت A/B باید boot_control HAL را در hardware/libhardware/include/hardware/boot_control.h پیادهسازی کنند. میتوانید پیادهسازیها را با استفاده از ابزار system/extras/bootctl و system/extras/tests/bootloader/ آزمایش کنید.
شما همچنین باید ماشین حالت نشان داده شده در زیر را پیادهسازی کنید:

هسته را تنظیم کنید
برای پیادهسازی بهروزرسانیهای سیستم A/B:
- سری پچهای کرنل زیر را (در صورت نیاز) انتخاب کنید:
- اگر بدون ramdisk و با استفاده از "boot as recovery" بوت میکنید، از cherrypick android-review.googlesource.com/#/c/158491/ استفاده کنید.
- برای تنظیم dm-verity بدون ramdisk، از دستور cherrypick android-review.googlesource.com/#/q/status:merged+project:kernel/common+branch:android-3.18+topic:A_B_Changes_3.18 استفاده کنید.
- مطمئن شوید که آرگومانهای خط فرمان هسته شامل آرگومانهای اضافی زیر باشند:
... که در آن مقدارskip_initramfs rootwait ro init=/init root="/dev/dm-0 dm=system none ro,0 1 android-verity <public-key-id> <path-to-system-partition>"<public-key-id>شناسه کلید عمومی مورد استفاده برای تأیید امضای جدول صحت است (برای جزئیات بیشتر، به dm-verity مراجعه کنید). - گواهی .X509 حاوی کلید عمومی را به حلقه کلید سیستم اضافه کنید:
- گواهی .X509 را که با فرمت
.derفرمت شده است، در ریشه دایرکتوریkernelکپی کنید. اگر گواهی .X509 با فرمت فایل.pemفرمت شده است، از دستورopensslزیر برای تبدیل از فرمت.pemبه.derاستفاده کنید:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
zImageطوری بسازید که گواهی را به عنوان بخشی از حلقه کلید سیستم در خود جای دهد. برای تأیید، ورودیprocfsرا بررسی کنید (نیاز به فعال بودنKEYS_CONFIG_DEBUG_PROC_KEYSدارد): درج موفقیتآمیز گواهی .X509 نشاندهندهی وجود کلید عمومی در حلقه کلید سیستم است (هایلایت نشاندهندهی شناسهی کلید عمومی است).angler:/# cat /proc/keys 1c8a217e I------ 1 perm 1f010000 0 0 asymmetri Android: 7e4333f9bba00adfe0ede979e28ed1920492b40f: X509.RSA 0492b40f [] 2d454e3e I------ 1 perm 1f030000 0 0 keyring .system_keyring: 1/4
- به جای فاصله،
#را قرار دهید و آن را به عنوان<public-key-id>در خط فرمان هسته وارد کنید. برای مثال، به جای<public-key-id>، عبارتAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40fرا وارد کنید.
- گواهی .X509 را که با فرمت
متغیرهای ساخت را تنظیم کنید
بوت لودرهای دارای قابلیت A/B باید معیارهای متغیر ساخت زیر را داشته باشند:
| باید برای هدف A/B تعریف شود |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk مراجعه کنید. میتوانید به صورت اختیاری مرحله dex2oat پس از نصب (اما قبل از راهاندازی مجدد) که در کامپایل توضیح داده شده است را انجام دهید. |
|---|---|
| برای هدف A/B اکیداً توصیه میشود |
|
| نمیتوان برای هدف A/B تعریف کرد |
|
| اختیاری برای ساختهای اشکالزدایی | PRODUCT_PACKAGES_DEBUG += update_engine_client |
تنظیم پارتیشنها (اسلاتها)
دستگاههای A/B به پارتیشن ریکاوری یا پارتیشن کش نیازی ندارند زیرا اندروید دیگر از این پارتیشنها استفاده نمیکند. پارتیشن داده اکنون برای بسته OTA دانلود شده استفاده میشود و کد تصویر ریکاوری روی پارتیشن بوت قرار دارد. تمام پارتیشنهایی که A/B-ed هستند باید به صورت زیر نامگذاری شوند (اسلاتها همیشه a ، b و غیره نامگذاری میشوند): boot_a ، boot_b ، system_a ، system_b ، vendor_a ، vendor_b .
حافظه پنهان
برای بهروزرسانیهای غیر A/B، از پارتیشن کش برای ذخیره بستههای OTA دانلود شده و ذخیره موقت بلوکها هنگام اعمال بهروزرسانیها استفاده میشد. هیچوقت روش خوبی برای اندازهگیری اندازه پارتیشن کش وجود نداشت: میزان بزرگی آن به بهروزرسانیهایی که میخواستید اعمال کنید بستگی داشت. بدترین حالت، یک پارتیشن کش به بزرگی تصویر سیستم بود. با بهروزرسانیهای A/B نیازی به ذخیره بلوکها نیست (زیرا شما همیشه در حال نوشتن روی پارتیشنی هستید که در حال حاضر استفاده نمیشود) و با پخش A/B نیازی به دانلود کل بسته OTA قبل از اعمال آن نیست.
بهبودی
دیسک رم ریکاوری اکنون در فایل boot.img قرار دارد. هنگام رفتن به ریکاوری، بوت لودر نمیتواند گزینه skip_initramfs را در خط فرمان هسته قرار دهد.
برای بهروزرسانیهای غیر A/B، پارتیشن ریکاوری شامل کدی است که برای اعمال بهروزرسانیها استفاده میشود. بهروزرسانیهای A/B توسط update_engine که در ایمیج سیستم بوت شده معمولی اجرا میشود، اعمال میشوند. هنوز یک حالت ریکاوری برای پیادهسازی بازنشانی به تنظیمات کارخانه و بارگذاری جانبی بستههای بهروزرسانی وجود دارد (که نام "بازیابی" از آن گرفته شده است). کد و دادههای حالت ریکاوری در پارتیشن بوت معمولی در یک ramdisk ذخیره میشوند. برای بوت شدن در ایمیج سیستم، بوتلودر به هسته میگوید که از ramdisk صرف نظر کند (در غیر این صورت دستگاه در حالت ریکاوری بوت میشود. حالت ریکاوری کوچک است (و بخش زیادی از آن از قبل در پارتیشن بوت بود)، بنابراین اندازه پارتیشن بوت افزایش نمییابد.
فستتاب
آرگومان slotselect باید در خط مربوط به پارتیشنهای A/B-ed باشد. برای مثال:
<path-to-block-device>/vendor /vendor ext4 ro wait,verify=<path-to-block-device>/metadata,slotselect
هیچ پارتیشنی نباید vendor نامگذاری شود. در عوض، پارتیشن vendor_a یا vendor_b انتخاب شده و در نقطه اتصال /vendor نصب میشود.
آرگومانهای اسلات هسته
پسوند اسلات فعلی باید یا از طریق یک گره درخت دستگاه (DT) خاص ( /firmware/android/slot_suffix ) یا از طریق خط فرمان هسته androidboot.slot_suffix یا آرگومان bootconfig منتقل شود.
به طور پیشفرض، فستبوت اسلات فعلی را روی دستگاه A/B فلش میکند. اگر بسته بهروزرسانی شامل ایمیجهایی برای اسلات دیگر و غیر فعلی نیز باشد، فستبوت آن ایمیجها را نیز فلش میکند. گزینههای موجود عبارتند از:
-
--slot SLOT. رفتار پیشفرض را نادیده میگیرد و از fastboot میخواهد که اسلاتی را که به عنوان آرگومان ارسال شده است، فلش کند. -
--set-active [ SLOT ]. اسلات را به عنوان فعال تنظیم میکند. اگر هیچ آرگومان اختیاری مشخص نشده باشد، اسلات فعلی به عنوان فعال تنظیم میشود. -
fastboot --help. جزئیات مربوط به دستورات را دریافت کنید.
اگر بوتلودر از fastboot پشتیبانی میکند، باید از دستور set_active <slot> که اسلات فعال فعلی را روی اسلات داده شده تنظیم میکند، پشتیبانی کند (این کار همچنین باید پرچم unbootable را برای آن اسلات پاک کند و تعداد تلاش مجدد را به مقادیر پیشفرض بازنشانی کند). بوتلودر همچنین باید از متغیرهای زیر پشتیبانی کند:
-
has-slot:<partition-base-name-without-suffix>در صورتی که پارتیشن مورد نظر از اسلاتها پشتیبانی کند، مقدار «yes» و در غیر این صورت مقدار «no» را برمیگرداند. -
current-slotپسوند اسلاتی را که از مرحلهی بعدی بوت خواهد شد، برمیگرداند. -
slot-countیک عدد صحیح برمیگرداند که تعداد اسلاتهای موجود را نشان میدهد. در حال حاضر، دو اسلات پشتیبانی میشوند، بنابراین این مقدار2است. -
slot-successful:<slot-suffix>. اگر اسلات داده شده به عنوان با موفقیت در حال بوت شدن علامت گذاری شده باشد، "بله" و در غیر این صورت "خیر" را برمیگرداند. -
slot-unbootable:<slot-suffix>. اگر اسلات داده شده به عنوان غیرقابل بوت علامت گذاری شده باشد، «بله» و در غیر این صورت «خیر» را برمیگرداند. - تعداد تلاشهای
slot-retry-count:<slot-suffix>باقیمانده برای بوت کردن اسلات داده شده.
برای مشاهده همه متغیرها، fastboot getvar all اجرا کنید.
تولید بستههای OTA
ابزارهای بسته OTA از همان دستورات مربوط به دستگاههای غیر A/B پیروی میکنند. فایل target_files.zip باید با تعریف متغیرهای ساخت برای هدف A/B تولید شود. ابزارهای بسته OTA به طور خودکار بستهها را در قالب بهروزرسانی A/B شناسایی و تولید میکنند.
مثالها:
- برای تولید یک OTA کامل:
./build/make/tools/releasetools/ota_from_target_files \ dist_output/tardis-target_files.zip \ ota_update.zip - برای تولید یک OTA افزایشی:
./build/make/tools/releasetools/ota_from_target_files \ -i PREVIOUS-tardis-target_files.zip \ dist_output/tardis-target_files.zip \ incremental_ota_update.zip
پیکربندی پارتیشنها
update_engine میتواند هر جفت پارتیشن A/B تعریفشده در یک دیسک را بهروزرسانی کند. یک جفت پارتیشن دارای یک پیشوند مشترک (مانند system یا boot ) و یک پسوند برای هر اسلات (مانند _a ) هستند. لیست پارتیشنهایی که تولیدکنندهی بار داده برای آنها بهروزرسانی تعریف میکند، توسط متغیر make از AB_OTA_PARTITIONS پیکربندی میشود.
برای مثال، اگر یک جفت پارتیشن bootloader_a و booloader_b گنجانده شده باشد ( _a و _b پسوندهای اسلات هستند)، میتوانید این پارتیشنها را با مشخص کردن موارد زیر در پیکربندی محصول یا برد بهروزرسانی کنید:
AB_OTA_PARTITIONS := \ boot \ system \ bootloader
تمام پارتیشنهایی که توسط update_engine بهروزرسانی میشوند، نباید توسط بقیه سیستم تغییر داده شوند. در طول بهروزرسانیهای افزایشی یا دلتا ، از دادههای باینری اسلات فعلی برای تولید دادهها در اسلات جدید استفاده میشود. هرگونه تغییر ممکن است باعث شود دادههای اسلات جدید در طول فرآیند بهروزرسانی، تأیید نشوند و بنابراین بهروزرسانی با شکست مواجه شود.
پیکربندی پس از نصب
شما میتوانید مرحلهی پس از نصب را برای هر پارتیشن بهروزرسانیشده با استفاده از مجموعهای از جفتهای کلید-مقدار، بهطور متفاوتی پیکربندی کنید. برای اجرای برنامهای که در /system/usr/bin/postinst در یک ایمیج جدید قرار دارد، مسیر مربوط به ریشهی سیستم فایل را در پارتیشن سیستم مشخص کنید.
برای مثال، usr/bin/postinst به system/usr/bin/postinst است (اگر از دیسک RAM استفاده نمیشود). علاوه بر این، نوع سیستم فایلی را که میخواهید به فراخوانی سیستمی mount(2) ارسال شود، مشخص کنید. موارد زیر را به فایلهای .mk محصول یا دستگاه (در صورت وجود) اضافه کنید:
AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=usr/bin/postinst \ FILESYSTEM_TYPE_system=ext4
کامپایل برنامهها
برنامهها میتوانند قبل از راهاندازی مجدد با تصویر سیستم جدید، در پسزمینه کامپایل شوند. برای کامپایل برنامهها در پسزمینه، موارد زیر را به پیکربندی دستگاه محصول (در device.mk محصول) اضافه کنید:
- اجزای بومی را در ساخت بگنجانید تا مطمئن شوید اسکریپت کامپایل و فایلهای باینری کامپایل شده و در تصویر سیستم گنجانده شدهاند.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
- اسکریپت کامپایل را به
update_engineوصل کنید تا به عنوان یک مرحله پس از نصب اجرا شود.# A/B OTA dexopt update_engine hookup AB_OTA_POSTINSTALL_CONFIG += \ RUN_POSTINSTALL_system=true \ POSTINSTALL_PATH_system=system/bin/otapreopt_script \ FILESYSTEM_TYPE_system=ext4 \ POSTINSTALL_OPTIONAL_system=true
برای کمک به نصب فایلهای از پیش انتخاب شده در پارتیشن سیستم دوم استفاده نشده، به نصب فایلهای DEX_PREOPT در اولین بوت مراجعه کنید.