יצרני ציוד מקורי (OEM) וספקי SoC שרוצים להטמיע עדכוני מערכת מסוג A/B צריכים לוודא שה-bootloader שלהם מטמיע את ה-HAL של boot_control ומעביר את הפרממטרים הנכונים לליבה.
הטמעת HAL לבקרת האתחול
מנהלי אתחול עם תמיכה ב-A/B חייבים להטמיע את ה-HAL של boot_control
ב-hardware/libhardware/include/hardware/boot_control.h
. אפשר לבדוק את ההטמעות באמצעות השירות system/extras/bootctl
ו-system/extras/tests/bootloader/
.
צריך גם להטמיע את מכונת המצבים שמוצגת בהמשך:

הגדרת הליבה
כדי להטמיע עדכוני מערכת מסוג A/B:
-
בוחרים את סדרת התיקונים הבאה לליבה (אם צריך):
- אם אתם מפעילים את המכשיר בלי ramdisk ומשתמשים באפשרות 'הפעלה כמצב שחזור', צריך לבחור את השינויים הרצויים מ-android-review.googlesource.com/#/c/158491/.
- כדי להגדיר את dm-verity בלי ramdisk, בוחרים את השינויים הרצויים מ-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
לספריית הבסיס (root) שלkernel
. אם אישור ה-X509 בפורמט של קובץ.pem
, משתמשים בפקודהopenssl
הבאה כדי להמיר אותו מפורמט.pem
לפורמט.der
:openssl x509 -in <x509-pem-certificate> -outform der -out <x509-der-certificate>
-
יוצרים את
zImage
כך שיכלול את האישור כחלק מ-keychain המערכת. כדי לוודא,בודקים את הרשומה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>
בשורת הפקודה של הליבה. לדוגמה, מעבירים את הערךAndroid:#7e4333f9bba00adfe0ede979e28ed1920492b40f
במקום<public-key-id>
.
-
מעתיקים את אישור ה-X509 בפורמט
הגדרת משתני build
מנהלי אתחול עם תמיכה ב-A/B חייבים לעמוד בקריטריונים הבאים של משתני build:
חובה להגדיר ליעד A/B |
/device/google/marlin/+/android-7.1.0_r1/device-common.mk . אם רוצים, אפשר לבצע את השלב dex2oat אחרי ההתקנה (אבל לפני ההפעלה מחדש) שמתואר בקטע הדרכה להדרכה.
|
---|---|
מומלץ מאוד ליעד A/B |
|
לא ניתן להגדיר יעד לבדיקה מסוג A/B |
|
אופציונלי לגרסאות build לניפוי באגים | PRODUCT_PACKAGES_DEBUG += update_engine_client |
הגדרת מחיצות (משבצות)
במכשירי A/B אין צורך במחיצה לשחזור או במחיצה של מטמון, כי מערכת Android כבר לא משתמשת במחיצות האלה. מחיצת הנתונים משמשת עכשיו לחבילת ה-OTA שהורדתם, וקוד קובץ האימג' לשחזור נמצא במחיצה של האתחול. צריך לתת שמות לכל המחיצות שמבצעים בהן בדיקת A/B באופן הבא (הסמכים תמיד נקראים a
, b
וכו'): boot_a
,
boot_b
, system_a
, system_b
, vendor_a
,
vendor_b
.
מטמון
בעדכונים שאינם A/B, מחיצה של מטמון שימשה לאחסון חבילות OTA שהורדתם ולשמירה זמנית של בלוקים בזמן החלת העדכונים. אף פעם לא הייתה דרך טובה לקבוע את הגודל של מחיצה המטמון: הגודל הנדרש שלה היה תלוי בעדכונים שרצית להחיל. במקרה הגרוע ביותר, מחיצה של מטמון בגודל של קובץ האימג' של המערכת. בעדכוני A/B אין צורך לשמור בלוקים (כי תמיד כותבים למחיצה שלא בשימוש כרגע), ובעדכוני A/B בסטרימינג אין צורך להוריד את חבילת ה-OTA כולה לפני החלתה.
שחזור
דיסק ה-RAM לשחזור נמצא עכשיו בקובץ boot.img
. כשעוברים לשחזור, מנהל האתחול לא יכול להוסיף את האפשרות skip_initramfs
לשורת הפקודה של הליבה.
בעדכונים שאינם A/B, מחיצת השחזור מכילה את הקוד שמשמש להטמעת עדכונים. העדכונים של A/B מופעלים על ידי הפעלת update_engine
בתמונת המערכת הרגילה שהופעל.
עדיין יש מצב שחזור שמשמשים להטמעת איפוס להגדרות המקוריות ולהעלאה צדדית של חבילות עדכון (ומכאן שם המצב 'שחזור'). הקוד והנתונים של מצב השחזור מאוחסנים במחיצה הרגילה של האתחול ב-ramdisk. כדי להפעיל את קובץ האימג' של המערכת, תוכנת האתחול מורה לליבה לדלג על ה-ramdisk (אחרת המכשיר יופעל במצב השחזור). גודל מצב השחזור קטן (והרבה ממנו כבר היה במחיצה לאתחול), כך שגודל מחיצת האתחול לא גדל.
Fstab
הארגומנט slotselect
חייב להיות בשורה של המחיצות שבהן מתבצעת בדיקת A/B. לדוגמה:
<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.
כברירת מחדל, fastboot מבצע פלאש של החריץ הנוכחי במכשיר A/B. אם חבילת העדכון מכילה גם תמונות לטלפון השני, שלא נמצא בשימוש כרגע, גם הן יימחקו על ידי fastboot. האפשרויות הזמינות כוללות:
-
--slot SLOT
. שינוי התנהגות ברירת המחדל והנחיה ל-fastboot לבצע הפעלה מהירה של החריץ שמוענק כארגומנטים. -
--set-active [SLOT]
. מגדירים את השקע כפעיל. אם לא צוין ארגומנט אופציונלי, החריץ הנוכחי מוגדר כפעיל. fastboot --help
. קבלת פרטים על פקודות.
אם מנהל האתחול מטמיע את fastboot, הוא אמור לתמוך בפקודה set_active <slot>
שמגדירה את החריץ הפעיל הנוכחי לחריץ הנתון (הפעולה הזו צריכה גם לנקות את הדגל של החריץ שלא ניתן לאתחל אותו ולאפס את מספר הניסיונות החוזרים לערכי ברירת המחדל). מנהל האתחול צריך לתמוך גם במשתנים הבאים:
-
has-slot:<partition-base-name-without-suffix>
. הפונקציה מחזירה את הערך 'yes' אם המחיצה נתונה תומכת בחריצי אחסון, ואת הערך 'no' אחרת. current-slot
. הפונקציה מחזירה את הסיומת של החריץ שממנו תתבצע ההפעלה הבאה.-
slot-count
. הפונקציה מחזירה מספר שלם שמייצג את מספר המשבצות הזמינות. בשלב הזה יש תמיכה בשני משבצות, ולכן הערך הזה הוא2
. -
slot-successful:<slot-suffix>
. הפונקציה מחזירה את הערך 'yes' אם החריץ הנתון סומן כטעינה מוצלחת, ואת הערך 'no' במקרה אחר. -
slot-unbootable:<slot-suffix>
. הפונקציה מחזירה את הערך 'yes' אם השקע הנתון מסומן כבלתי ניתן לאתחול, ואת הערך 'no' במקרים אחרים. -
slot-retry-count:<slot-suffix>
. מספר הניסיונות החוזרים שנותרו לניסיון להפעיל את החריץ הנתון.
כדי להציג את כל המשתנים, מריצים את הפקודה fastboot getvar all
.
יצירת חבילות OTA
כלים לחבילות OTA פועלים לפי אותן פקודות כמו הפקודות למכשירים שאינם A/B. כדי ליצור את הקובץ target_files.zip
, צריך להגדיר את משתני ה-build של היעד לבדיקה 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
). רשימת המחיצות שלגביהן ה-generator של עומס העבודה מגדיר עדכון מוגדרת על ידי משתנה ה-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 של המוצר):
-
צריך לכלול את הרכיבים המקומיים ב-build כדי לוודא שהסקריפט והקובצי הבינארי של הידור ימולאו ויכללו בקובץ האימג' של המערכת.
# A/B OTA dexopt package PRODUCT_PACKAGES += otapreopt_script
-
מחברים את סקריפט ה-compilation ל-
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 בהפעלה הראשונה מוסבר איך להתקין את הקבצים שנבחרו מראש במחיצה השנייה של המערכת שלא בשימוש.