עליך להשתמש ב-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.