HIDL בנוי סביב ממשקים, סוג מופשט המשמש בשפות מונחה עצמים להגדרת התנהגויות. כל ממשק הוא חלק מחבילה.
חבילות
שמות חבילות יכולים לכלול רמות משנה כגון package.subpackage
. ספריית השורש של חבילות HIDL שפורסמו היא hardware/interfaces
או vendor/vendorName
(למשל vendor/google
עבור מכשירי Pixel). שם החבילה יוצר ספריית משנה אחת או יותר תחת ספריית הבסיס; כל הקבצים המגדירים חבילה נמצאים באותה ספרייה. לדוגמה, ניתן למצוא package android.hardware.example.extension.light@2.0
תחת hardware/interfaces/example/extension/light/2.0
.
הטבלה הבאה מפרטת קידומות ומיקומים של חבילות:
קידומת חבילה | מקום | סוגי ממשקים |
---|---|---|
android.hardware.* | hardware/interfaces/* | HAL |
android.frameworks.* | frameworks/hardware/interfaces/* | מסגרות/ קשורות |
android.system.* | system/hardware/interfaces/* | מערכת/ קשור |
android.hidl.* | system/libhidl/transport/* | הליבה |
ספריית החבילה מכילה קבצים עם סיומת .hal
. כל קובץ חייב להכיל הצהרת package
עם שם החבילה והגרסה שהקובץ הוא חלק ממנה. הקובץ types.hal
, אם קיים, אינו מגדיר ממשק אלא מגדיר סוגי נתונים הנגישים לכל ממשק בחבילה.
הגדרת ממשק
מלבד types.hal
, כל קובץ .hal
אחר מגדיר ממשק. ממשק מוגדר בדרך כלל באופן הבא:
interface IBar extends IFoo { // IFoo is another interface // embedded types struct MyStruct {/*...*/}; // interface methods create(int32_t id) generates (MyStruct s); close(); };
ממשק ללא extends
מפורשת משתרע באופן מרומז מ- android.hidl.base@1.0::IBase
(בדומה ל- java.lang.Object
ב-Java.) ממשק IBase, מיובא באופן מרומז, מצהיר על מספר שיטות שמורות שאסור ולא ניתן להצהרה מחדש בממשקים מוגדרי משתמש או בשימוש אחר. שיטות אלו כוללות:
-
ping
-
interfaceChain
-
interfaceDescriptor
-
notifySyspropsChanged
-
linkToDeath
-
unlinkToDeath
-
setHALInstrumentation
-
getDebugInfo
-
debug
-
getHashChain
מייבא
הצהרת import
היא מנגנון HIDL לגישה לממשקי חבילה וסוגים בחבילה אחרת. הצהרת import
מתייחסת לשתי ישויות:
- ישות הייבוא , שיכולה להיות חבילה או ממשק; ו
- ישות היבוא , שגם היא יכולה להיות חבילה או ממשק.
הישות המייבאת נקבעת לפי המיקום של הצהרת import
. כאשר ההצהרה נמצאת בתוך types.hal
של חבילה, מה שמיובא גלוי לכל החבילה; זהו ייבוא ברמת החבילה . כאשר ההצהרה נמצאת בתוך קובץ ממשק, הישות המיובאת היא הממשק עצמו; זהו ייבוא ברמת הממשק .
הישות המיובאת נקבעת לפי הערך שאחרי מילת המפתח import
. הערך אינו חייב להיות שם מלא; אם רכיב מושמט, הוא מתמלא אוטומטית במידע מהחבילה הנוכחית. עבור ערכים מתאימים לחלוטין, מקרי הייבוא הבאים נתמכים:
- יבוא חבילה שלמה . אם הערך הוא שם חבילה וגרסה (תחביר המתואר להלן), אז החבילה כולה מיובאת לישות המייבאת.
- יבוא חלקי . אם הערך הוא:
- ממשק, ה-
types.hal
של החבילה והממשק הזה מיובאים לישות המייבאת. - UDT מוגדר ב-
types.hal
, אז רק אותו UDT מיובא לישות המייבאת (סוגים אחרים ב-types.hal
אינם מיובאים).
- ממשק, ה-
- יבוא מסוגים בלבד . אם הערך משתמש בתחביר של ייבוא חלקי שתואר לעיל, אך עם
types
מילות המפתח במקום שם ממשק, רק ה-UDTs ב-types.hal
של החבילה המיועדת מיובאים.
הישות המייבאת מקבלת גישה לשילוב של:
- UDTs הנפוצים של החבילה המיובאת המוגדרים ב-
types.hal
; - ממשקי החבילה המיובאת (ליבוא חבילה שלמה) או ממשק מוגדר (לייבוא חלקי) לצורך הפקתם, העברת נקודות עזר אליהם ו/או ירושה מהם.
הצהרת הייבוא משתמשת בתחביר-שם-סוג מלא כדי לספק את השם והגרסה של החבילה או הממשק המיובאים:
import android.hardware.nfc@1.0; // import a whole package import android.hardware.example@1.0::IQuux; // import an interface and types.hal import android.hardware.example@1.0::types; // import just types.hal
תורשת ממשק
ממשק יכול להיות הרחבה של ממשק שהוגדר קודם לכן. הרחבות יכולות להיות אחד משלושת הסוגים הבאים:
- ממשק יכול להוסיף פונקציונליות לממשק אחר, תוך שילוב ה-API שלו ללא שינוי.
- החבילה יכולה להוסיף פונקציונליות לאחת אחרת, לשלב את ה-API שלה ללא שינוי.
- ממשק יכול לייבא סוגים מחבילה או מממשק ספציפי.
ממשק יכול להרחיב רק ממשק אחד אחר (ללא ירושה מרובה). כל ממשק בחבילה עם מספר גרסה מינור שאינו אפס חייב להרחיב ממשק בגרסה הקודמת של החבילה. לדוגמה, אם ממשק IBar
בגרסה 4.0 של derivative
החבילה מבוסס על (מרחיב) ממשק IFoo
בגרסה 1.2 של החבילה original
, ונוצרת גרסה 1.3 של החבילה original
, גרסה 4.1 של IBar
לא יכולה להרחיב את גרסה 1.3 של IFoo
. במקום זאת, גרסה 4.1 IBar
חייבת להרחיב את גרסה 4.0 IBar
, הקשורה לגרסה 1.2 של IFoo
. IBar
גרסה 5.0 יכולה להרחיב את IFoo
גרסה 1.3, אם תרצה בכך.
הרחבות ממשק אינן מרמזות על תלות בספרייה או הכללת HAL צולבת בקוד שנוצר - הן פשוט מייבאות את מבנה הנתונים והגדרות השיטה ברמת HIDL. כל שיטה ב-HAL חייבת להיות מיושמת באותו HAL.
הרחבות ספקים
במקרים מסוימים, הרחבות ספקים יוטמעו כתת-מחלקה של אובייקט הבסיס המייצג את ממשק הליבה שהם מרחיבים. אותו אובייקט יירשם תחת השם והגרסה הבסיסית HAL, ותחת השם והגרסת HAL (הספק) של התוסף.
גירסאות
לחבילות יש גרסאות, ולממשקים יש את הגרסה של החבילה שלהם. גרסאות מבוטאות בשני מספרים שלמים, עיקרי . קטין .
- הגרסאות העיקריות אינן תואמות לאחור. הגדלת מספר הגרסה הראשית מאפסת את מספר הגרסה המשנית ל-0.
- גרסאות מינוריות תואמות לאחור. הגדלת המספר הקטן מציינת שהגרסה החדשה יותר תואמת לחלוטין לאחור לגרסה הקודמת. ניתן להוסיף מבני נתונים ושיטות חדשות, אך לא ניתן לשנות מבני נתונים קיימים או חתימות שיטה.
מספר גרסאות עיקריות או משניות של HAL יכולות להיות נוכחות במכשיר בו-זמנית. עם זאת, יש להעדיף גרסה מינורית על פני גרסה עיקרית מכיוון שקוד לקוח שעובד עם ממשק גרסה מינורית קודמת יעבוד גם עם גרסאות מינוריות מאוחרות יותר של אותו ממשק. לפרטים נוספים על ניהול גרסאות והרחבות של ספקים, ראה גירסאות HIDL .
סיכום פריסת הממשק
סעיף זה מסכם כיצד לנהל חבילת ממשק HIDL (כגון hardware/interfaces
) ומאחד מידע המוצג לאורך סעיף HIDL. לפני הקריאה, ודא שאתה מכיר את גירסת HIDL , את מושגי הגיבוב ב-Hidl-gen , את פרטי העבודה עם HIDL באופן כללי ואת ההגדרות הבאות:
טווח | הַגדָרָה |
---|---|
ממשק יישומים בינארי (ABI) | ממשק תכנות יישומים + כל קישורים בינאריים הנדרשים. |
שם מלא (fqName) | שם כדי להבחין בין סוג hidl. דוגמה: android.hardware.foo@1.0::IFoo . |
חֲבִילָה | חבילה המכילה ממשק HIDL וסוגים. דוגמה: android.hardware.foo@1.0 . |
שורש החבילה | חבילת שורש המכילה את ממשקי HIDL. דוגמה: ממשק HIDL android.hardware נמצא בשורש החבילה android.hardware.foo@1.0 . |
נתיב שורש החבילה | מיקום בעץ המקור של אנדרואיד שאליו ממופה שורש חבילה. |
להגדרות נוספות, ראה טרמינולוגיה של HIDL.
ניתן למצוא כל קובץ ממיפוי שורש החבילה והשם המלא שלו
שורשי החבילה מצוינים ל- hidl-gen
בתור הארגומנט -r android.hardware:hardware/interfaces
. לדוגמה, אם החבילה היא vendor.awesome.foo@1.0::IFoo
וה- hidl-gen
נשלח -r vendor.awesome:some/device/independent/path/interfaces
, אז קובץ הממשק צריך להיות ממוקם ב- $ANDROID_BUILD_TOP/some/device/independent/path/interfaces/foo/1.0/IFoo.hal
.
בפועל, מומלץ לספק או OEM בשם awesome
לשים את הממשקים הסטנדרטיים שלהם ב- vendor.awesome
. לאחר בחירת נתיב חבילה, אסור לשנות אותו מכיוון שהוא אפוי ב-ABI של הממשק.
מיפוי נתיב חבילה צריך להיות ייחודי
לדוגמה, אם יש לך -rsome.package:$PATH_A
ו- -rsome.package:$PATH_B
, $PATH_A
חייב להיות שווה ל- $PATH_B
עבור ספריית ממשק עקבית (זה גם מקל בהרבה על ממשקי גרסאות ).
לשורש החבילה חייב להיות קובץ ניהול גרסאות
אם אתה יוצר נתיב חבילה כגון -r vendor.awesome:vendor/awesome/interfaces
, עליך ליצור גם את הקובץ $ANDROID_BUILD_TOP/vendor/awesome/interfaces/current.txt
, שאמור להכיל גיבוב של ממשקים שנעשו באמצעות -Lhash
אפשרות ב- hidl-gen
(על זה נדון בהרחבה ב- Hashing עם hidl-gen ).
ממשקים נכנסים למיקומים בלתי תלויים במכשיר
בפועל, מומלץ לשתף ממשקים בין סניפים. זה מאפשר שימוש מרבי בקוד ובדיקה מקסימלית של קוד במכשירים ובמקרי שימוש שונים.