ממשקי HAL זמינים באופן דינמי

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

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

שינויים בהגדרות HAL

כדי לבצע כיבוי דינמי, צריך לדעת אילו תהליכים משרתים את ממשקי ה-HAL (המידע הזה עשוי להיות שימושי גם בהמשך בהקשרים אחרים), וגם לא להפעיל תהליכים בזמן האתחול ולא להפעיל אותם מחדש (עד שתתבצע בקשה חוזרת) כשהם יוצאים.

# some init.rc script associated with the HAL
service vendor.some-service-name /vendor/bin/hw/some-binary-service
    # init language extension, provides information of what service is served
    # if multiple interfaces are served, they can be specified one on each line
    interface android.hardware.light@2.0::ILight default
    # restarted if hwservicemanager dies
    # would also cause the hal to start early during boot if disabled wasn't set
    class hal
    # will not be restarted if it exits until it is requested to be restarted
    oneshot
    # will only be started when requested
    disabled
    # ... other properties

שינויים ב-init וב-hwservicemanager

כדי לבצע כיבוי דינמי, צריך גם שה-hwservicemanager יורה ל-init להפעיל את השירותים המבוקשים. ב-Android 9, השדה init כולל שלוש הודעות בקרה נוספות (למשל ctl.start): ctl.interface_start,‏ ctl.interface_stop ו-ctl.interface_restart. אפשר להשתמש בהודעות האלה כדי לשלוח אות ל-init להפעלה ולהשבתה של ממשקי חומרה ספציפיים. כשמבקשים שירות שלא רשום, hwservicemanager מבקש להפעיל את השירות. עם זאת, ב-HAL דינמי לא נדרש שימוש באף אחד מהם.

קביעת יציאה מ-HAL

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

כדי לבצע כיבוי דינמי, צריך כמה כללי מדיניות כדי להחליט מתי להפעיל HAL ומתי לכבות HAL. אם HAL מחליט לצאת מסיבה כלשהי, הוא יופעל מחדש באופן אוטומטי כשיהיה צורך בו שוב, באמצעות המידע שסופק בהגדרת ה-HAL והתשתית שסופקו על ידי השינויים ב-init וב-hwservicemanager. אפשר להשתמש בכמה שיטות שונות, כולל:

  • HAL יכול לבחור לבצע קריאה ל-exit על עצמו אם מישהו קורא ל-API דומה או קרוב. צריך לציין את ההתנהגות הזו בממשק HAL המתאים.
  • HALs יכולים להיסגר כשהמשימה שלהם מסתיימת (מתועד בקובץ HAL).

מחזורי חיים אוטומטיים

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

  • רושמים את השירות ב-C++ באמצעות LazyServiceRegistrar במקום פונקציית החבר registerAsService, לדוגמה:
    // only one instance of LazyServiceRegistrar per process
    LazyServiceRegistrar registrar;
    registrar.registerAsService(myHidlService /* , "default" */);
  • מוודאים שלקוח ה-HAL שומר הפניה ל-HAL ברמה העליונה (הממשק שמירשם ב-hwservicemanager) רק כשמשתמשים בו. כדי למנוע עיכובים אם ההפניה הזו תושלך בשרשור של hwbinder שממשיך לפעול, הלקוח צריך גם לבצע קריאה ל-IPCThreadState::self()->flushCommands() אחרי השמטת ההפניה, כדי לוודא שמתקבלת הודעה למנהל ה-binder על השינויים במספר ההפניות המשויך.