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

‫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 (הטווח הראשון, לפני סיום או פסיק) חייב להיות אחד מהערכים הבאים, שמחולקים לסיבות ברמת הליבה, סיבות חזקות וסיבות גלויות:

  • kernel set:
    • "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) ולהשתמש בהזדמנות הזו כפורום לדיונים בנושא בעיות שקשורות לסיבת האתחול.