HIDL מבוסס על ממשקים, סוג מופשט שמשמש כדי להגדיר התנהגויות. כל ממשק הוא חלק מחבילה.
חבילות
לשמות של חבילות יכולות להיות רמות משנה כמו package.subpackage
.
ספריית השורש של חבילות HIDL שפורסמו היא hardware/interfaces
או vendor/vendorName
(לדוגמה, vendor/google
ל-Pixel
מכשירים). שם החבילה יוצר ספריית משנה אחת או יותר ברמה הבסיסית (root)
directory; כל הקבצים שמגדירים חבילה נמצאים באותה ספרייה. לדוגמה,
אפשר למצוא את 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/* |
frameworks/ related |
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
, הפרטים שמיובאים גלויים בחבילה כולה.
זהו ייבוא ברמת החבילה. כשההצהרה נמצאת בתוך
קובץ ממשק, הישות המיובאת היא הממשק עצמו; זו
ייבוא ברמת interface-level.
הישות המיובאת נקבעת לפי הערך שמופיע אחרי import
במילת מפתח. הערך לא חייב להיות שם שמוגדר במלואו; אם רכיב
שהושמט, הוא ממולא אוטומטית במידע מהחבילה הנוכחית.
כדי לקבל ערכים מוגדרים במלואם, תרחישי הייבוא הבאים נתמכים:
- ייבוא של כל חבילה. אם הערך הוא שם חבילה (התחביר שמתואר בהמשך), החבילה כולה מיובאת המיובאת.
- ייבוא חלקי. אם הערך הוא:
- ממשק, ה-
types.hal
של החבילה והממשק הזה יובא לישות המיובאת. - UDT מוגדר ב-
types.hal
, ואז רק ה-UDT מיובא אליו. הישות המיובאת (סוגים אחרים ב-types.hal
לא מיובאים).
- ממשק, ה-
- ייבוא סוגים בלבד. אם הערך משתמש בתחביר של
ייבוא חלקי שמתואר למעלה, אבל במקום זאת עם מילת המפתח
types
של שם ממשק, רק את ה-UDT ב-types.hal
של החבילות מיובאות.
הישות המיובאת מקבלת גישה לשילוב של:
- רכיבי ה-UDT הנפוצים של החבילה המיובאת מוגדרים ב-
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
IBar
גרסה 4.0, שמקושרת לגרסה 1.2 של IFoo
.
ייתכן שגרסה 5.0 של IBar
תרחיב את גרסה 1.3 של IFoo
, אם
הרצויה.
תוספי ממשק לא מרמזים על תלות של ספרייה או הכללה בין HAL בקוד שנוצר, הם פשוט מייבאים את מבנה הנתונים והשיטה הגדרות ברמת HIDL. כל שיטה ב-HAL צריכה להיות מוטמעת HAL.
תוספי ספקים
במקרים מסוימים, תוספי ספקים מוטמעים כמחלקה משנה של של האובייקט הבסיסי שמייצג את ממשק הליבה שהם מרחיבים. אותו אובייקט הוא רשומים בשם ובגרסה של HAL הבסיסי, ובתחתית השם והגרסה של HAL (ספק).
ניהול גרסאות
לחבילות יש גרסאות, ובממשקים יש את גרסת החבילה. הגרסאות מבוטאות בשני מספרים שלמים, גדול.משני.
- גרסאות ראשיות לא תואמות לאחור. מצטבר מספר הגרסה הראשית מאפס את מספר הגרסה המשנית ל-0.
- גרסאות קטנות תואמות לאחור. הוספת מספר משני מציין שהגרסה החדשה יותר תואמת באופן מלא בגרסה הקודמת. אפשר להוסיף שיטות ומבנים חדשים של נתונים, אבל לא קיימות עדיין שיטות עשויים להיות שינויים במבני נתונים או בחתימות של שיטות.
במכשיר יכולות להיות כמה גרסאות ראשיות או משניות של HAL בו-זמנית. עם זאת, יש לתת עדיפות לגרסה משנית על פני גרסה ראשית כי קוד לקוח שפועל עם הממשק הקודם של הגרסה המשנית פועל גם עם גרסאות משניות מאוחרות יותר של אותו הממשק. לקבלת מידע נוסף לפרטים על ניהול גרסאות ותוספי ספקים, ראו ניהול גרסאות של HIDL
סיכום פריסת הממשק
קטע זה מסכם את האופן שבו ניתן לנהל חבילת ממשק HIDL (כגון
hardware/interfaces
) ומאחד את המידע המוצג
לכל אורך הקטע HIDL. לפני הקריאה, צריך לוודא שאתם יודעים
ניהול גרסאות HIDL,
גיבוב עם
במושגים של hidl-gen, את הפרטים של העבודה עם
HIDL באופן כללי, וההגדרות הבאות:
מונח | הגדרה |
---|---|
application Binary Interface (ABI) | ממשק תכנות יישומים וכן כל קישור בינארי כנדרש. |
שם מוגדר במלואו (fqName) | שם כדי להבדיל בין סוג ה-hidl. דוגמה:
android.hardware.foo@1.0::IFoo |
חבילה | חבילה שמכילה ממשק וסוגים של HIDL. דוגמה:
android.hardware.foo@1.0 |
הרמה הבסיסית של החבילה | חבילת בסיס שמכילה את ממשקי HIDL. דוגמה: ממשק HIDL
android.hardware נמצא ברמה הבסיסית (root) של החבילה
android.hardware.foo@1.0 . |
נתיב הרמה הבסיסית של החבילה | המיקום בעץ המקור של Android שאליו ממופה שורש החבילה. |
להגדרות נוספות, אפשר לעיין ב-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
(נדון בהרחבה בנושא
גיבוב באמצעות
hidl-gen).
הממשקים לא תלויים במכשיר מיקומים גיאוגרפיים
בפועל, מומלץ לשתף ממשקים בין הסתעפויות. הזה מאפשרת שימוש חוזר בקוד מקסימלי ובדיקה מקסימלית של קוד במגוון פורמטים מכשירים ותרחישים לדוגמה.