פריסת מחיצה

ב-Android 10, מערכת הקבצים ברמה הבסיסית (root) כבר לא נכלל ב-ramdisk.img ובמקום זאת ממוזג עם system.img (כלומר, system.img תמיד נוצר בתור אם הוגדר BOARD_BUILD_SYSTEM_ROOT_IMAGE). מכשירים בהשקה עם Android 10:

  • להשתמש בפריסת מחיצות של מערכת בתור הבסיס (שנאכפת באופן אוטומטי על ידי build ללא אפשרויות לשינוי ההתנהגות).
  • חייב להשתמש ב-ramdisk, הנדרש ל-dm-ליניארי.
  • חובה להגדיר את BOARD_BUILD_SYSTEM_ROOT_IMAGE ל-false. ההגדרה הזו משמשת רק להבחנה בין מכשירים שמשתמשים ב-ramdisk ומכשירים שלא משתמשים בשרת רדיסק (ובמקום זאת מתקינים system.img ישירות).

המשמעות של הגדרת מערכת ברמה הבסיסית (root) שונה בין Android 9 לבין Android 10. במערכת של Android 9 ברמה הבסיסית (root) הגדרה אישית, BOARD_BUILD_SYSTEM_ROOT_IMAGE מוגדר true, שמאלץ את ה-build למזג את מערכת הקבצים ברמה הבסיסית (root) system.img לאחר מכן טוענים את system.img כקובץ הרמה הבסיסית (root) מערכת (rootfs). ההגדרה הזו חובה במכשירים מושק עם Android 9, אבל אופציונלי למכשירים שמשדרגים Android 9 ולמכשירים עם גרסאות קודמות של Android. במכשיר Android 10 הגדרות מערכת ברמה הבסיסית (root), ה-build תמיד ממזג את $TARGET_SYSTEM_OUT ואת $TARGET_ROOT_OUT ל- system.img; ההגדרה הזאת היא התנהגות ברירת המחדל בכל המכשירים עם Android 10.

ב-Android 10 מתבצעים שינויים נוספים בתמיכה מחיצות דינמיות, מערכת חלוקה למחיצות (partitioning) במרחב המשתמשים שמאפשרת לבצע עדכונים אלחוטיים (OTA) יצירה, שינוי גודל או השמדה של מחיצות. כחלק מהשינוי הזה, Linux הליבה לא יכולה יותר לטעון את מחיצת המערכת הלוגית במכשירים שפועלים Android 10, לכן הפעולה הזו מטופלת על ידי בפעימה הזו.

בקטעים הבאים מתוארות דרישות המערכת ברמה הבסיסית (root) עבור עדכוני OTA שמיועדים למערכת בלבד, מספקים הנחיות לגבי עדכון מכשירים לשימוש במערכת בתור הבסיס (כולל שינויים בפריסת מחיצות ודרישות ליבה (kernel) של dm-verity. עבור לפרטים על השינויים ב-ramdisk, ראו Ramdisk מחיצות.

מידע על זמני OTA שמיועדים למערכת בלבד

זמני OTA (OTA) למערכות בלבד, שמאפשרים לעדכן גרסאות ל-Android system.img וגם product.img ללא שינוי נוסף מחיצות, דורשת פריסת מחיצות של מערכת כשורש. כל המכשירים עם Android 10 חייב להשתמש בפריסת מחיצות של מערכת כשורש כדי להפעיל OTA או מערכת בלבד.

לפרטים על מכשירי A/B ומכשירים שהם לא מסוג A/B, אפשר לעיין במאמר עדכוני מערכת (חלקיים).

שימוש בשכבת-על של ספק (<=AOSP 14)

שכבת-על של ספק מאפשרת שכבת-על של שינויים ב-vendor מחיצה בזמן ההפעלה של המכשיר. שכבת-על של ספק היא קבוצה של מודולים של ספקים המחיצה product שמופיעה מעל vendor למחיצה בזמן אתחול המכשיר, והחלפה והוספה למודולים הקיימים.

עם אתחול המכשיר, התהליך init משלים את טעינת שלב וקורא את מאפייני ברירת המחדל. לאחר מכן מתבצע חיפוש /product/vendor_overlay/<target_vendor_version> וטעינות כל ספריית משנה בספריית המחיצות vendor התואמת שלה, אם התנאים הבאים מתקיימים:

  • /vendor/<overlay_dir> קיים.
  • /product/vendor_overlay/<target_vendor_version>/<overlay_dir> יש הקשר קובץ זהה לזה של /vendor/<overlay_dir>.
  • init מורשה לטעון בהקשר של הקובץ של /vendor/<overlay_dir>.

הטמעת שכבת-על של ספק

התקנת קובצי שכבת-על של ספק ב- /product/vendor_overlay/<target_vendor_version> הקבצים האלה תיצור שכבת-על של המחיצה vendor כשהמכשיר יופעל, ותחליף קבצים בעלי אותו שם ולהוסיף קבצים חדשים. שכבת-העל של הספק לא יכולה להסיר קבצים מהמחיצה vendor.

לקובצי שכבת-על של ספקים צריך להיות אותו הקשר לקובץ כמו קובצי היעד הם מחליפים במחיצה vendor. כברירת מחדל, הקבצים ספריית /product/vendor_overlay/<target_vendor_version> כוללים את ההקשר vendor_file. אם יש חוסר התאמה בהקשר של הקובץ בין קובצי שכבת-על של הספק לבין הקבצים שהם מחליפים, צריך לציין מדיניות ספציפית למכשיר. הקשר הקובץ מוגדר ברמת הספרייה. אם ההקשר של קובץ ספריית שכבת-העל של הספק לא תואם לספריית היעד, וההקשר הנכון של הקובץ לא מצוין במדיניות הספציפית למכשיר, שספריית שכבת-על של ספק לא מופיעה כשכבת-על של ספריית היעד.

כדי להשתמש בשכבת-על של ספק, הליבה צריכה להפעיל את OverlayFS על ידי הגדרה CONFIG_OVERLAY_FS=y כמו כן, צריך למזג את הליבה ליבה נפוצה מגרסה 4.4 ואילך, או מתוקנת באמצעות "overlayfs: override_creds=off option bypass creator_cred".

דוגמה להטמעת שכבת-על של ספק

ההליך הזה מדגים הטמעת שכבת-על של ספק ששכבת-על ספריות /vendor/lib/*, /vendor/etc/* ו- /vendor/app/*.

  1. הוספת קובצי ספקים מוכנים מראש ב- device/<vendor>/<target>/vendor_overlay/<target_vendor_version>/:

    device/google/device/vendor_overlay/28/lib/libfoo.so
    device/google/device/vendor_overlay/28/lib/libbar.so
    device/google/device/vendor_overlay/28/etc/baz.xml
    device/google/device/vendor_overlay/28/app/qux.apk
    
  2. מתקינים את קובצי הספק המוכנים מראש ב- product/vendor_overlay אינץ' device/google/device/device.mk:

    PRODUCT_COPY_FILES += \
        $(call find-copy-subdir-files,*,device/google/device/vendor_overlay,$(TARGET_COPY_OUT_PRODUCT)/vendor_overlay)
    
  3. הגדרת הקשרי קבצים אם קובצי המחיצה של vendor המיועדים יש הקשרים שהם לא vendor_file. כי /vendor/lib/* משתמש בהקשר של vendor_file, לא כוללת את הספרייה הזו.

    הוספת הטקסט הבא אל device/google/device-sepolicy/private/file_contexts:

    /(product|system/product)/vendor_overlay/[0-9]+/etc(/.*)?   u:object_r:vendor_configs_file:s0
    /(product|system/product)/vendor_overlay/[0-9]+/app(/.*)?   u:object_r:vendor_app_file:s0
    
  4. מתן הרשאה לתהליך init לטעון את שכבת-העל של הספק בקובץ הקשרים שהם לא vendor_file. כי init לתהליך הזה כבר יש הרשאה לטעון בהקשר של vendor_file, בדוגמה הזו לא מוגדר המדיניות vendor_file.

    הוספת הטקסט הבא אל device/google/device-sepolicy/public/init.te:

    allow init vendor_configs_file:dir mounton;
    allow init vendor_app_file:dir mounton;
    

אימות שכבת-העל של הספק

כדי לאמת את תצורת שכבת-העל של הספק, יש להוסיף קבצים ב /product/vendor_overlay/<target_vendor_version>/<overlay_dir> ולבדוק אם הקבצים מופיעים כשכבת-על מעל לקבצים /vendor/<overlay_dir>.

לגרסאות build של userdebug יש מודול בדיקה עבור Atest:

$ atest -v fs_mgr_vendor_overlay_test

עדכון למערכת בתור הרמה הבסיסית (root)

כדי לעדכן מכשירים שאינם מסוג A/B כך שישתמשו במערכת בתור הרמה הבסיסית (root), צריך לעדכן את סכמת החלוקה למחיצות (partitioning) עבור boot.img ו-system.img, הוגדרה ב-dm-verity ולהסיר את יחסי התלות של האתחול ברמה הבסיסית (root) הספציפית למכשיר תיקיות.

עדכון מחיצות

בשונה ממכשירי A/B שנעשה בהם שימוש מחדש ב-/boot המחיצה recovery, במכשירים שאינם מסוג A/B חייבים להשאיר את המחיצה /recovery בנפרד, כי אין להם את המחיצה של משבצת הזמן החלופית (לדוגמה, מ-boot_a עד boot_b). אם /recovery הוא הוסר במכשיר שאינו A/B ובוצע באופן דומה לסכימת A/B, מצב שחזור עלולות לקרוס במהלך עדכון שנכשל במחיצה /boot. עבור לכן, המחיצה /recovery חייבת להיות למחיצה נפרדת מ-/boot למכשירים שאינם מסוג A/B, כלומר שתמונת השחזור ממשיכה להתעדכן באיחור (כלומר (או במכשירים עם Android מגרסה 8.1.0 ומטה).

בטבלה הבאה מפורטים ההבדלים בין מחיצות תמונה במכשירים שאינם מסוג A/B לפני ואחרי Android 9.

תמונה Ramdisk (לפני 9) מערכת בתור הרמה הבסיסית (root) (אחרי 9)
boot.img מכיל ליבה וramdisk.img:
ramdisk.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/ (mount point)
    - vendor/ (mount point)
    - odm/ (mount point)
    ...
מכיל ליבה (kernel) רגילה של אתחול בלבד.
recovery.img מכיל ליבה (kernel) לשחזור ושחזור ramdisk.img
system.img מכיל:
system.img
  -/
    - bin/
    - etc
    - vendor -> /vendor
    - ...
מכיל את התוכן הממוזג של המקור system.img וגם ramdisk.img:
system.img
  -/
    - init.rc
    - init
    - etc -> /system/etc
    - system/
      - bin/
      - etc/
      - vendor -> /vendor
      - ...
    - vendor/ (mount point)
    - odm/ (mount point)
    ...

המחיצות עצמן לא משתנות. גם בשימוש ב-ramdisk וגם במערכת כשורש את סכימת החלוקה הבאה:

  • /boot
  • /system
  • /system
  • /recovery
  • /vendor וכו'

הגדרת dm-verity

במערכת בתור ברמה הבסיסית (root), הליבה צריכה לטעון את system.img מתחת / (נקודת טעינה) עם dm-verity. AOSP תומך ב-dm-verity הבא של system.img.

vboot 1.0

ב-vboot 1.0, הליבה צריכה לנתח ספציפי ל-Android מטא-נתונים מופעלים /system, ואז המרה ל הגדרת פרמטרים של dm-verity להגדרת dm-verity (נדרשים תיקוני הליבה האלה). הדוגמה הבאה מציגה הגדרות שקשורות ל-dm-verity עבור מערכת בתור שורש ב- שורת הפקודה בליבה (kernel):

ro root=/dev/dm-0 rootwait skip_initramfs init=/init
dm="system none ro,0 1 android-verity /dev/sda34"
veritykeyid=id:7e4333f9bba00adfe0ede979e28ed1920492b40f

vboot 2.0

ל-vboot 2.0 (AVB), תוכנת האתחול חייבת לשלב external/avb/libavb, שמנתחת את hashtree descriptor עבור /system, משלים המרה אותו dm-verity params, ולבסוף מעביר את הפרמטרים ליבה (kernel) דרך שורת הפקודה של הליבה. (מתארי גיבוב (hash) של /system יכול להיות שהוא ב-/vbmeta או ב-/system עצמו).

vboot 2.0 דורש את תיקוני הליבה הבאים:

הדוגמה הבאה מציגה הגדרות שקשורות ל-dm-verity עבור מערכת בתור שורש ב- שורת הפקודה בליבה (kernel):

ro root=/dev/dm-0 rootwait  skip_initramfs init=/init

dm="1 vroot none ro 1,0 5159992 verity 1
PARTUUID=00000016-0000-0000-0000-000000000000
PARTUUID=00000016-0000-0000-0000-000000000000 4096 4096 644999 644999
sha1 d80b4a8be3b58a8ab86fad1b498640892d4843a2
8d08feed2f55c418fb63447fec0d32b1b107e42c 10 restart_on_corruption
ignore_zero_blocks use_fec_from_device
PARTUUID=00000016-0000-0000-0000-000000000000 fec_roots 2 fec_blocks
650080 fec_start 650080"

שימוש בתיקיות בסיס ספציפיות למכשיר

עם מערכת בתור הבסיס, אחרי תמונת המערכת הגנרית (GSI) מהבהב במכשיר (ולפני ההפעלה) בדיקות של ספק הבדיקה), כל תיקיות בסיס ספציפיות למכשיר שנוספו עם BOARD_ROOT_EXTRA_FOLDERS לא קיימים כי כל התוכן של ספריית השורש הוחלף ב- מערכת GSI ברמת השורש. הסרת התיקיות האלה עלולה לגרום למכשיר בלתי ניתן להפעלה אם קיימת תלות בתיקיות ברמה הבסיסית (root) שספציפיות למכשיר (לדוגמה, הן משמשות כנקודות טעינה).

כדי למנוע את הבעיה הזו, אין להשתמש ב-BOARD_ROOT_EXTRA_FOLDERS כדי להוסיף תיקיות בסיס ספציפיות למכשיר. אם צריך לציין טעינה ספציפית למכשיר נקודות, צריך להשתמש ב-/mnt/vendor/<mount point> (נוסף רשימות שינויים). נקודות הטעינה האלה, שספציפיות לספק, יכולות מצוין ישירות גם בעץ המכשירים של fstab (לשלב הראשון נטענים) ואת הקובץ /vendor/etc/fstab.{ro.hardware} בלי הגדרות נוספות (כפי ש-fs_mgr יוצר אותן במסגרת /mnt/vendor/* באופן אוטומטי).