הסיבה הקנונית להפעלה

‫Android 9 כוללת את השינויים הבאים במפרט של סיבת ההפעלה של טוען האתחול.

סיבות להפעלה

טוען האתחול משתמש במשאבי חומרה וזיכרון שזמינים באופן ייחודי כדי לקבוע למה המכשיר הופעל מחדש, ואז הוא מוסיף את androidboot.bootreason=<reason> לשורת הפקודה של ליבת Android כדי להעביר את ההחלטה הזו. ‫init ואז מתרגם את שורת הפקודה הזו כדי להפיץ אותה למאפיין Android‏ bootloader_boot_reason_prop (ro.boot.bootreason). במכשירים עם Android מגרסה 12 ואילך, שמופעלים עם ליבה בגרסה 5.10 ואילך, ‫androidboot.bootreason=<reason> נוסף ל-bootconfig במקום לשורת הפקודה של הליבה.

מפרטים של סיבת ההפעלה

בגרסאות קודמות של Android, הפורמט של סיבת האתחול לא כלל רווחים, היה באותיות קטנות בלבד, כלל מעט דרישות (למשל, לדיווח על kernel_panic, watchdog, cold/warm/hard) והתחשב בסיבות ייחודיות אחרות. ההגדרה החופשית הזו הובילה להצפה של מאות מחרוזות מותאמות אישית (ולפעמים חסרות משמעות) של סיבות להפעלה, מה שהפך את המצב לבלתי נסבל. החל מגרסת Android הנוכחית, המומנטום של תוכן כמעט בלתי ניתן לניתוח או חסר משמעות שמוגש על ידי טוען האתחול יצר בעיות תאימות עבור bootloader_boot_reason_prop.

עם השקת Android 9, צוות Android מבין של-bootloader_boot_reason_prop מדור קודם יש מומנטום משמעותי ואי אפשר לשכתב אותו בזמן ריצה. לכן, כל שיפור במפרט של סיבת האתחול צריך לנבוע מאינטראקציות עם מפתחי תוכנת האתחול ומשינויים במערכת הקיימת. לכן, צוות Android:

  • ליצור קשר עם מפתחי תוכנת האתחול כדי לעודד אותם:
    • צריך לספק סיבות קנוניות, ניתנות לניתוח וניתנות לזיהוי לbootloader_boot_reason_prop.
    • להשתתף ברשימה system/core/bootstat/bootstat.cpp kBootReasonMap.
  • הוספת מקור מבוקר שאפשר לשכתב בזמן ריצה של system_boot_reason_prop (sys.boot.reason). קבוצה מוגבלת של אפליקציות מערכת (כמו bootstat ו-init) יכולה לשכתב את המאפיין הזה, אבל אפשר להעניק לכל האפליקציות הרשאות sepolicy לקריאת המאפיין.
  • הודעה למשתמשים על סיבת האתחול כדי להמתין עד להרכבת נתוני המשתמש לפני שסומכים על התוכן במאפיין סיבת האתחול של המערכת system_boot_reason_prop.

למה כל כך מאוחר? ‫bootloader_boot_reason_prop זמין בשלב מוקדם של האתחול, אבל הוא נחסם על ידי מדיניות האבטחה של Android לפי הצורך, כי הוא מייצג מידע לא מדויק, שלא ניתן לניתוח ולא קנוני. ברוב המקרים, רק מפתחים עם ידע מעמיק במערכת ההפעלה צריכים לגשת למידע הזה. ‫API מעודן, ניתן לניתוח וקנוני לסיבת האתחול עם system_boot_reason_prop, שאפשר לאסוף באופן מהימן ומדויק רק אחרי שנתוני המשתמשים הועלו. פרטים נוספים:

  • לפני שנתוני המשתמשים מועלים, המשתנה system_boot_reason_prop יכיל את הערך מ-bootloader_boot_reason_prop.
  • אחרי שהנתונים של המשתמש מותקנים, יכול להיות ש-system_boot_reason_prop יעודכן כדי לעמוד בדרישות או כדי לדווח על מידע מדויק יותר.

לכן, ב-Android 9, התקופה שצריך להמתין לפני שאפשר לקבל באופן רשמי את סיבת האתחול היא ארוכה יותר. במקום להיות מדויקת באופן מיידי באתחול (עם bootloader_boot_reason_prop), היא זמינה רק אחרי שהנתונים של המשתמשים הועלו (עם system_boot_reason_prop).

הלוגיקה של Bootstat תלויה ב-bootloader_boot_reason_prop יותר אינפורמטיבי ותואם. אם הנכס הזה משתמש בפורמט צפוי, הוא משפר את הדיוק של כל התרחישים של הפעלה מחדש וכיבוי מבוקרים, וכתוצאה מכך משפר ומרחיב את הדיוק והמשמעות של system_boot_reason_prop.

פורמט קנוני של סיבת ההפעלה

הפורמט הקנוני של סיבת האתחול של bootloader_boot_reason_prop ב-Android 9 הוא:

<reason>,<subreason>,<detail>…

כללי עיצוב:

  • אותיות קטנות
  • ללא רווחים (שימוש בקו תחתון)
  • כל התווים שניתן להדפיס
  • מופרדים בפסיקים reason, subreason ומופע אחד או יותר של detail.
    • reason חובה שמייצג את הסיבה בעדיפות הכי גבוהה לכך שהמכשיר נאלץ להפעיל מחדש או לכבות.
    • מחרוזת אופציונלית subreason שמייצגת סיכום קצר של הסיבה להפעלה מחדש או לכיבוי של המכשיר (או מי הפעיל מחדש או כיבה את המכשיר).
    • ערך אחד או יותר של detail (אופציונלי). התג detail יכול להפנות למערכת משנה כדי לעזור לקבוע איזו מערכת ספציפית הובילה לתוצאה subreason. אפשר לציין כמה ערכים של detail, בדרך כלל לפי היררכיה של חשיבות. עם זאת, אפשר גם לדווח על כמה ערכים של detail באותה מידה של חשיבות.

ערך ריק בשדה bootloader_boot_reason_prop נחשב לא חוקי (כי הוא מאפשר לסוכנים אחרים להוסיף סיבת אתחול בדיעבד).

דרישות לגבי הסיבה

הערך שניתן עבור reason (הטווח הראשון, לפני סיום או פסיק) חייב להיות אחד מהערכים הבאים, שמחולקים לסיבות ברמת הליבה, סיבות חזקות וסיבות לא מדויקות:

  • קבוצת ליבות:
    • "watchdog"
    • "kernel_panic"
  • קבוצה חזקה:
    • "recovery"
    • "bootloader"
  • blunt set:
    • "cold". בדרך כלל מציין איפוס מלא של כל המכשירים, כולל הזיכרון.
    • "hard". בדרך כלל מציין שהמצב של החומרה אופס ושהתוכן הקבוע צריך להישמר ב-ramoops.
    • "warm". בדרך כלל מציין שהזיכרון והמכשירים שומרים על מצב מסוים, ושהגיבוי ramoops (ראו מנהל התקן pstore בקרנל) מכיל תוכן קבוע.
    • "shutdown"
    • "reboot". בדרך כלל, המשמעות היא שהמצב של ramoops לא ידוע, וגם המצב של החומרה לא ידוע. הערך הזה הוא כללי כי הערכים של cold, hard ו-warm מספקים רמזים לגבי עומק האיפוס של המכשיר.

טועני אתחול צריכים לספק קבוצת ליבה או קבוצה גלויה reason, ומומלץ מאוד לספק subreason אם אפשר לקבוע אותו. לדוגמה, לחיצה ארוכה על מקש ההפעלה, שעשויה להיות לה גיבוי ramoops או לא, תגרום להצגת סיבת האתחול "reboot,longkey".

אף reason ראשון לא יכול להיות חלק מ-subreason או מ-detail. עם זאת, מכיוון שלא ניתן ליצור סיבות להגדרת ליבה במרחב המשתמש, יכול להיות שנעשה שימוש חוזר ב-"watchdog" אחרי סיבה להגדרה גסה, יחד עם פרטים על המקור (לדוגמה, "reboot,watchdog,service_manager_unresponsive" או "reboot,software,watchdog").

הסיבות להפעלה מחדש לא צריכות לדרוש ידע פנימי מומחה כדי לפענח אותן, או שהן צריכות להיות קריאות לאנשים עם דוח אינטואיטיבי. דוגמאות: ‫"shutdown,vbxd" (לא טוב), "shutdown,uv" (טוב יותר), "shutdown,undervoltage" (מועדף).

שילובים של סיבה ותת-סיבה

מערכת Android שומרת לעצמה קבוצה של שילובי reason-subreason שאסור להעמיס עליהם יותר מדי בשימוש רגיל, אבל אפשר להשתמש בהם במקרים ספציפיים אם השילוב משקף באופן מדויק את התנאי המשויך. דוגמאות לשילובים שמורים:

  • "reboot,userrequested"
  • "shutdown,userrequested"
  • "shutdown,thermal" (מאת thermald)
  • "shutdown,battery"
  • "shutdown,battery,thermal" (מאת BatteryStatsService)
  • "reboot,adb"
  • "reboot,shell"
  • "reboot,bootloader"
  • "reboot,recovery"

פרטים נוספים מופיעים בkBootReasonMap בsystem/core/bootstat/bootstat.cpp ובהיסטוריית יומן השינויים של git שמשויכת למאגר המקור של Android.

דיווח על סיבות לאתחול

כל הסיבות לאתחול, בין אם הן מגיעות מתוכנת האתחול או מתועדות בסיבה הקנונית לאתחול, חייבות להיות מתועדות בקטע kBootReasonMap של system/core/bootstat/bootstat.cpp. הרשימה kBootReasonMap כוללת סיבות שעומדות בדרישות וסיבות מדור קודם שלא עומדות בדרישות. מפתחי Bootloader צריכים לרשום כאן רק סיבות חדשות לתאימות (ואסור לרשום סיבות לאי-תאימות אלא אם המוצר כבר נשלח ואי אפשר לשנות אותו).

מומלץ מאוד להשתמש ברשומות קיימות ועומדות בדרישות ב-system/core/bootstat/bootstat.cpp ולהימנע משימוש במחרוזת שלא עומדת בדרישות. ככלל, הוא:

  • OK כדי לדווח על "kernel_panic" מ-bootloader, כי יכול להיות ש-bootstat יוכל לבדוק את ramoops כדי לחדד את הסיבות המשניות ל-kernel_panic signatures ל-system_boot_reason_prop קנוני.
  • לא מומלץ לדווח על מחרוזת לא תואמת ב-kBootReasonMap (למשל "panic") מ-bootloader), כי זה יפגע בסופו של דבר ביכולת לשפר את reason.

לדוגמה, אם kBootReasonMap מכיל את "wdog_bark", מפתח של bootloader צריך:

  • מעבר ל"watchdog,bark" והוספה לרשימה בkBootReasonMap.
  • כדאי להסביר מה זה "bark" למי שלא מכיר את הטכנולוגיה, ולבדוק אם יש subreason משמעותי יותר.

אימות התאימות של סיבת האתחול

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

לכן, כדי שה-bootloader יעמוד בדרישות, מפתחי ה-bootloader צריכים לפעול בהתאם לרוח הכללים וההנחיות שמתוארים למעלה. אנחנו קוראים למפתחים כאלה לתרום ל-AOSP (ספציפית ל-system/core/bootstat/bootstat.cpp) ולנצל את ההזדמנות הזו כפורום לדיונים בנושא בעיות שקשורות לסיבת האתחול.