יצירת ממשק HAL

עליך להשתמש ב-HIDL כדי לתאר את כל דגלי ה-build המשמשים להידור מותנה של המסגרת. יש לקבץ דגלי בנייה רלוונטיים ולכלול אותם בקובץ .hal יחיד. השימוש ב-HIDL לציון פריטי תצורה כולל את היתרונות הבאים:

  • בגרסה (כדי להוסיף פריטי תצורה חדשים, ספקים/OEM חייבים להרחיב במפורש את ה-HAL)
  • מתועד היטב
  • בקרת גישה באמצעות SELinux
  • בדיקת שפיות עבור פריטי תצורה דרך חבילת הבדיקה של ספקים (בדיקת טווח, בדיקת תלות בין פריטים וכו')
  • ממשקי API שנוצרו אוטומטית ב-C++ וגם ב-Java

זיהוי דגלי בנייה המשמשים את המסגרת

התחל על ידי זיהוי תצורות ה-build המשמשות להידור מותנה של המסגרת, ולאחר מכן נטוש תצורות מיושנות כדי להקטין את הסט. לדוגמה, קבוצת דגלי הבנייה הבאה מזוהה עבור surfaceflinger :

  • TARGET_USES_HWC2
  • TARGET_BOARD_PLATFORM
  • TARGET_DISABLE_TRIPLE_BUFFERING
  • TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
  • NUM_FRAMEBUFFER_SURFACE_BUFFERS
  • TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK
  • VSYNC_EVENT_PHASE_OFFSET_NS
  • SF_VSYNC_EVENT_PHASE_OFFSET_NS
  • PRESENT_TIME_OFFSET_FROM_VSYNC_NS
  • MAX_VIRTUAL_DISPLAY_DIMENSION

יצירת ממשק HAL

ניתן לגשת לתצורות בנייה עבור תת-מערכת דרך ממשק HAL, בעוד שממשקים למתן ערכי תצורה מקובצים בחבילת HAL android.hardware.configstore (כרגע בגרסה 1.0). לדוגמה, כדי ליצור קובץ ממשק HAL עבור surfaceflinger , ב- hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal :

package android.hardware.configstore@1.0;

interface ISurfaceFlingerConfigs {
    // TO-BE-FILLED-BELOW
};

לאחר יצירת קובץ .hal , הפעל את hardware/interfaces/update-makefiles.sh כדי להוסיף את קובץ .hal החדש לקבצי Android.bp ו- Android.mk .

הוספת פונקציות עבור דגלים לבנות

עבור כל דגל בנייה, הוסף פונקציה חדשה לממשק. לדוגמה, hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal :

interface ISurfaceFlingerConfigs {
    disableTripleBuffering() generates(OptionalBool ret);
    forceHwcForVirtualDisplays() generates(OptionalBool ret);
    enum NumBuffers: uint8_t {
        USE_DEFAULT = 0,
        TWO = 2,
        THREE = 3,
    };
    numFramebufferSurfaceBuffers() generates(NumBuffers ret);
    runWithoutSyncFramework() generates(OptionalBool ret);
    vsyncEventPhaseOffsetNs generates (OptionalUInt64 ret);
    presentTimeOffsetFromSyncNs generates (OptionalUInt64 ret);
    maxVirtualDisplayDimension() generates(OptionalInt32 ret);
};

בעת הוספת פונקציה:

  • היו תמציתיים עם שמות. הימנע מהמרת שמות משתנים של makefile לשמות פונקציות וזכור כי קידומות TARGET_ ו- BOARD_ אינן נחוצות עוד.
  • הוסף תגובות. עזור למפתחים להבין את מטרת פריט התצורה, כיצד הוא משנה את התנהגות המסגרת, ערכים חוקיים ומידע רלוונטי אחר.

סוגי החזרת פונקציות יכולים להיות Optional[Bool|String|Int32|UInt32|Int64|UInt64] . סוגים מוגדרים ב- types.hal באותה ספרייה ועוטפים ערכים פרימיטיביים בשדה המציין אם הערך מצוין על ידי ה-HAL; אם לא, נעשה שימוש בערך ברירת המחדל.

struct OptionalString {
    bool specified;
    string value;
};

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

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

לדוגמה, אפשרות לצבירה של שני דגלי בנייה למבנה יחיד hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal היא:

 interface ISurfaceFlingerConfigs {
    // other functions here
    struct SyncConfigs {
        OptionalInt64 vsyncEventPhaseoffsetNs;
        OptionalInt64 presentTimeoffsetFromSyncNs;
    };
    getSyncConfigs() generates (SyncConfigs ret);
    // other functions here
};

חלופות לפונקציית HAL אחת

כחלופה לשימוש בפונקציית HAL יחידה עבור כל דגלי הבנייה, ממשק HAL מספק גם פונקציות פשוטות כגון getBoolean(string key) ו- getInteger(string key) . key=value בפועל מאוחסנים בקבצים נפרדים ושירות HAL מספק ערכים על ידי קריאה/ניתוח של קבצים אלה.

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

ממשקים בודדים ומרובים

העיצוב של ממשק HAL עבור פריטי תצורה מציג שתי אפשרויות:

  • ממשק יחיד המכסה את כל פריטי התצורה
  • ממשקים מרובים, שכל אחד מהם מכסה קבוצה של פריטי תצורה קשורים

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

בגלל בעיות אלה, אנדרואיד משתמשת במספר ממשקים עם ממשק HAL יחיד עבור קבוצה של פריטי תצורה קשורים. לדוגמה, ISurfaceflingerConfigs עבור פריטי תצורה הקשורים surfaceflinger , ו- IBluetoothConfigs עבור פריטי תצורה הקשורים ל- Bluetooth.