צריך להשתמש ב-HIDL כדי לתאר את כל דגלי ה-build שמשמשים באופן מותנה
את ה-framework. דגלי build רלוונטיים חייבים להיות מקובצים ולכלול
קובץ .hal
יחיד. שימוש ב-HIDL לציון פריטי תצורה
כוללת את היתרונות הבאים:
- גרסאות (כדי להוסיף פריטי הגדרה חדשים, ספקים/יצרני ציוד מקורי חייבים להרחיב באופן מפורש את HAL)
- מתועד היטב
- בקרת גישה באמצעות SELinux
- בדיקת רמת השפיות לפריטי תצורה באמצעות בדיקת ספק חבילה (בדיקת טווח, בדיקת תלות בין פריטים וכו')
- ממשקי API שנוצרים באופן אוטומטי ב-C++ וב-Java
זיהוי הדגלים של build שמשמשים את ה-framework
מתחילים בזיהוי הגדרות ה-build שמשמשות להדר באופן מותנה
framework, ואז נוטשים הגדרות מיושנות כדי להקטין את הקבוצה. לדוגמה,
הקבוצה הבאה של דגלי 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
הגישה להגדרות build של מערכת משנה מתבצעת דרך ממשק 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
קבצים.
הוספת פונקציות ל-build דגלים
לכל דגל build, מוסיפים פונקציה חדשה לממשק. לדוגמה, ב-
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_
לא נחוצות יותר. - הוספת תגובות. לעזור למפתחים להבין את המטרה של config, האופן שבו הוא משנה את ההתנהגות של מסגרת, ערכים חוקיים ופרטים רלוונטיים אחרים מידע.
סוגי ההחזרה של הפונקציות יכולים להיות
Optional[Bool|String|Int32|UInt32|Int64|UInt64]
הסוגים מוגדרים
ב-types.hal
באותה ספרייה ועוטפים ערכים ראשוניים עם
שדה שמציין אם הערך מצוין על ידי HAL. אם לא, ברירת המחדל
נעשה שימוש בערך שלו.
struct OptionalString { bool specified; string value; };
במקרים המתאימים, הגדירו את טיפוס הטיפוסים שמייצג בצורה הטובה ביותר את סוג
ומשתמשים ב-enum הזה כסוג ההחזרה. בדוגמה שלמעלה,
NumBuffers
טיפוסים בני מנייה (enum) מוגדר כדי להגביל את מספר הערכים התקינים
ערכים. כשמגדירים סוגי נתונים מותאמים אישית כאלה, צריך להוסיף שדה או ערך enum (ל
לדוגמה, USE_DEFAULT
) לציון אם הערך לא צוין או לא צוין.
מאת HAL.
לא חובה שדגל אחד של build יהפוך לפונקציה אחת HIDL. בעלי מודולים יכולים במקום זאת לקבץ דגלי build בעלי קשר הדוק לתוך של מבנה יש פונקציה שמחזירה את המבנה (פעולה זו יכולה להפחית מספר הקריאות לפונקציה).
לדוגמה, אפשרות לצבירת שני דגלי build במבנה אחד
באזור 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 יחידה לכל דגלי ה-build, HAL
הממשק מספק גם פונקציות פשוטות כמו getBoolean(string
key)
ו-getInteger(string key)
. בפועל
key=value
זוגות מאוחסנים בקבצים נפרדים ובשירות HAL
שמספק ערכים על ידי קריאה/ניתוח של הקבצים האלה.
אמנם קל להגדיר את הגישה הזו, אבל היא לא כוללת את היתרונות מסופק על ידי HIDL (אכיפה של ניהול גרסאות, קלות תיעוד, בקרת גישה) ולכן היא לא מומלצת.
ממשק יחיד וממשקים מרובים
העיצוב של ממשק HAL לפריטי תצורה מציג בחירות:
- ממשק אחד שמכסה את כל פריטי התצורה
- מספר ממשקים, שכל אחד מהם כולל קבוצה של הגדרות אישיות קשורות פריטים
קל יותר להשתמש בממשק אחד, אבל קשה יותר לתחזק אותו כי פריטי התצורה יתווספו לקובץ היחיד. נוסף על כך, בקרת גישה לא פרטנית, כך שתהליך שמקבלים גישה לממשק יכול לקרוא כל פריטי התצורה (לא ניתן לקבל גישה לקבוצה חלקית של פריטי תצורה ). לחלופין, אם לא ניתנה גישה, לא ניתן לקבל את פריטי ההגדרה נקראו.
עקב הבעיות האלה, מערכת Android משתמשת בממשקים מרובים עם ממשק HAL אחד
של קבוצת פריטי תצורה קשורים. לדוגמה,
ISurfaceflingerConfigs
עבור surfaceflinger
-related
ו-IBluetoothConfigs
להגדרות שקשורות ל-Bluetooth
של הגדרות אישיות.