Google is committed to advancing racial equity for Black communities. See how.
דף זה תורגם על ידי Cloud Translation API.
Switch to English

גרסאות

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

מבנה קוד HIDL

קוד HIDL מאורגן בסוגים, ממשקים וחבילות המוגדרים על ידי המשתמש:

  • סוגים מוגדרים על ידי המשתמש (UDT) . HIDL מספק גישה לקבוצת סוגי נתונים פרימיטיביים שבהם ניתן להשתמש כדי לחבר סוגים מורכבים יותר באמצעות מבנים, איגודים וספירות. UDT מועברים לשיטות ממשק, וניתן להגדירם ברמת חבילה (המשותפת לכל הממשקים) או באופן מקומי לממשק.
  • ממשקים . כאבן בניין בסיסית של HIDL, ממשק מורכב מהצהרות UDT ושיטות. ממשקים יכולים גם לרשת מממשק אחר.
  • חבילות . מארגן ממשקי HIDL קשורים וסוגי הנתונים עליהם הם פועלים. חבילה מזוהה על ידי שם וגרסה וכוללת את הדברים הבאים:
    • קובץ הגדרת סוג נתונים הנקרא types.hal .
    • אפס ממשקים או יותר, כל אחד בקובץ ה- .hal שלו.

סוגי הקבצים מסוג הגדרת סוג types.hal מכילים types.hal בלבד (כל ה- UDT ברמת החבילה נשמרים בקובץ יחיד). ייצוגים בשפת היעד זמינים לכל הממשקים בחבילה.

פילוסופיית גרסאות

חבילת HIDL (כגון android.hardware.nfc ), לאחר שפורסמה עבור גרסה נתונה (כגון 1.0 ), אינה ניתנת לשינוי; אי אפשר לשנות את זה. שינויים בממשקים שבחבילה או כל שינוי ב- UDT שלה יכולים להתרחש רק בחבילה אחרת .

ב- HIDL, גרסאות חלות ברמת החבילה, לא ברמת הממשק, וכל הממשקים וה- UDT בחבילה חולקים את אותה גרסה. גרסאות החבילה עוקבות אחר גרסאות סמנטיות ללא רמת התיקון ורכיבי metadata build. בתוך חבילה נתונה, בליטה בגרסת מינור מרמזת על כך שהגרסה החדשה של החבילה אינה תואמת לאחור עם החבילה הישנה וחבילה בגרסה הראשית מרמזת כי הגרסה החדשה של החבילה אינה תואמת לאחור עם החבילה הישנה.

מבחינה רעיונית, חבילה יכולה להתייחס לחבילה אחרת באחת מכמה דרכים:

  • בכלל לא .
  • הרחבה תואמת לאחור ברמת החבילה . זה קורה בשינוי מהדורות חדשות של גרסה משנית (תיקון מצטבר הבא) של חבילה; לחבילה החדשה יש שם וגרסה ראשית זהה לחבילה הישנה, ​​אך גרסה מינורית גבוהה יותר. מבחינה פונקציונלית, החבילה החדשה היא קבוצת על של החבילה הישנה, ​​כלומר:
    • ממשקים ברמה העליונה של חבילת האב קיימים בחבילה החדשה, אם כי בממשקים עשויים להיות שיטות חדשות, ממשקי ממשק חדשים מקומיים (הרחבה ברמת הממשק המתוארת להלן) ו- UDT חדשים ב- types.hal .
    • ניתן להוסיף לחבילה החדשה גם ממשקים חדשים.
    • כל סוגי הנתונים של חבילת האב נמצאים בחבילה החדשה וניתן לטפל בהם בשיטות (שאולי מיושמות מחדש) מהחבילה הישנה.
    • ניתן להוסיף גם סוגי נתונים חדשים לשימוש בשיטות חדשות של ממשקים קיימים שקדמו להם, או באמצעות ממשקים חדשים.
  • הרחבה תואמת לאחור ברמת הממשק . החבילה החדשה יכולה גם להרחיב את החבילה המקורית על ידי מורכבת מממשקים נפרדים מבחינה לוגית שמספקים פונקציונליות נוספת ולא הליבה. לצורך זה עשוי להיות רצוי להלן:
    • ממשקים בחבילה החדשה צריכים להשתמש בסוגי הנתונים של החבילה הישנה.
    • ממשקים בחבילה חדשה עשויים להאריך ממשקים של חבילה ישנה אחת או יותר.
  • הרחב את חוסר התאימות המקורי לאחור . זהו גרסה עיקרית של החבילה ולא צריך להיות שום מתאם בין השניים. במידה שיש, זה יכול לבוא לידי ביטוי עם שילוב של סוגים מהגרסה הישנה של החבילה, וירושה של תת קבוצה של ממשקי חבילה ישנה.

בניית ממשקים

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

טרבל תומך ברכיב ספקים ורכיבי מערכת בהם ניתן vendor.img את vendor.img במכשיר ואת system.img . יש להגדיר באופן מפורש ויסודי את כל האינטראקציות בין vendor.img ו- system.img כדי שיוכלו להמשיך לעבוד במשך שנים רבות. זה כולל משטחי API רבים, אך משטח עיקרי הוא מנגנון ה- IPC ש- HIDL משתמש בו לתקשורת בין- vendor.img בגבול system.img / vendor.img .

דרישות

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

  • ניתן לתאר ב- HIDL ישירות (באמצעות enums structts וכו ') עם שמות ומשמעות סמנטיים.
  • ניתן לתאר על ידי תקן ציבורי כגון ISO / IEC 7816.
  • ניתן לתאר על ידי תקן חומרה או פריסה פיזית של חומרה.
  • יכול להיות נתונים אטומים (כגון מפתחות ציבוריים, מזהים וכו ') במידת הצורך.

אם משתמשים בנתונים אטומים, יש לקרוא אותם רק על ידי צד אחד של ממשק HIDL. לדוגמה, אם vendor.img קוד נותן מרכיב על system.img הודעה מחרוזת או vec<uint8_t> נתונים, נתונים שלא ניתן לנתחו ידי system.img עצמה; ניתן להחזיר אותו רק ל- vendor.img לפרשנות. כאשר מעבירים ערך מ- vendor.img לקוד ספק ב- system.img או למכשיר אחר, יש לתאר במדויק את פורמט הנתונים ואופן פירושם והם עדיין חלק מהממשק .

הנחיות

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

פריסת קוד HIDL

HIDL כולל חבילות ליבה וספקים.

ממשקי ליבת HIDL הם אלה שצוינו על ידי גוגל. החבילות שאליהן שייכות מתחילות עם android.hardware. ונקראים לפי תת-מערכת, פוטנציאלית עם רמות שמות מקוננות. לדוגמא, חבילת ה- NFC נקראת android.hardware.nfc וחבילת המצלמה היא android.hardware.camera . באופן כללי, לחבילת ליבה יש את השם android.hardware. [ name1 ]. [ name2 ] .... לחבילות HIDL יש גרסה בנוסף לשמם. לדוגמה, החבילה android.hardware.camera עשויה להיות בגרסה 3.4 ; זה חשוב מכיוון שגרסת החבילה משפיעה על מיקומה בעץ המקור.

כל חבילות הליבה ממוקמות תחת hardware/interfaces/ במערכת הבנייה. החבילה android.hardware. [ name1 ]. [ name2 ] ... בגרסה $m.$n נמצאת תחת hardware/interfaces/name1/name2//$m.$n/ ; חבילה android.hardware.camera גרסה 3.4 נמצאת hardware/interfaces/camera/3.4/. הספריה hardware/interfaces/camera/3.4/. מיפוי מקודד קיים בין קידומת החבילה android.hardware. hardware/interfaces/ הנתיב hardware/interfaces/ .

חבילות שאינן ליבות (ספקיות) הן אלה המיוצרות על ידי ספק SoC או ODM. הקידומת לחבילות שאינן ליבות היא vendor.$(VENDOR).hardware. כאשר $(VENDOR) מתייחס לספק SoC או OEM / ODM. זה ממפה vendor/$(VENDOR)/interfaces הנתיבים vendor/$(VENDOR)/interfaces העץ (מיפוי זה מקודד גם הוא קשה).

שמות מסוגים מוגדרים על ידי המשתמש המלאים

ב- HIDL, לכל UDT יש שם מוסמך לחלוטין המורכב משם UDT, שם החבילה שבו מוגדר ה- UDT וגרסת החבילה. השם המלא מלא משמש רק כאשר מוצהרים מופעים מהסוג ולא במקום בו מוגדר הסוג עצמו. לדוגמא, נניח לחבילה android.hardware.nfc, גרסה 1.0 מגדירה מבנה בשם NfcData . באתר ההצהרה (בין אם ב- types.hal ובין אם במסגרת הצהרת ממשק), ההצהרה פשוט קובעת:

struct NfcData {
    vec<uint8_t> data;
};

בעת הכרזה על מופע מסוג זה (בין אם במבנה נתונים ובין אם כפרמטר מתודה), השתמש בשם הסוג המלא:

android.hardware.nfc@1.0::NfcData

התחביר הכללי הוא PACKAGE @ VERSION :: UDT , שם:

  • PACKAGE היא שם מופרדת נקודה של חבילה HIDL (למשל, android.hardware.nfc ).
  • VERSION הוא הפורמט המופרד בין הנקודות העיקריות.מינור של החבילה (למשל, 1.0 ).
  • UDT הוא השם המופרד באמצעות נקודה של HIDL UDT. מכיוון ש- HIDL תומך ב- UDT מקונן וממשקי HIDL יכולים להכיל UDTs (סוג של הצהרה מקוננת), נקודות משמשות לגישה לשמות.

לדוגמא, אם ההצהרה המקוננת הבאה הוגדרה בקובץ הסוגים הנפוצים בחבילה android.hardware.example גרסה 1.0 :

// types.hal
package android.hardware.example@1.0;
struct Foo {
    struct Bar {
        // …
    };
    Bar cheers;
};

השם המלא של Bar הוא android.hardware.example@1.0::Foo.Bar . אם, בנוסף להיותם בחבילה הנ"ל, ההצהרה המקוננת הייתה בממשק בשם IQuux :

// IQuux.hal
package android.hardware.example@1.0;
interface IQuux {
    struct Foo {
        struct Bar {
            // …
        };
        Bar cheers;
    };
    doSomething(Foo f) generates (Foo.Bar fb);
};

השם המלא של Bar הוא android.hardware.example@1.0::IQuux.Foo.Bar .

בשני המקרים, Bar יכול להיות המכונה Bar רק במסגרת ההכרזה של Foo . ברמת החבילה או הממשק, עליכם להתייחס Bar דרך Foo : Foo.Bar , כמו בהצהרת השיטה doSomething לעיל. לחלופין, תוכל להכריז על השיטה בצורה יותר מילולית כ:

// IQuux.hal
doSomething(android.hardware.example@1.0::IQuux.Foo f) generates (android.hardware.example@1.0::IQuux.Foo.Bar fb);

ערכי ספירה מלאים

אם UDT הוא סוג enum, אז לכל ערך מסוג enum יש שם מוסמך לחלוטין שמתחיל בשם המוסמך במלואו של סוג enum, ואחריו נקודתיים, ואז אחריו שם ערך enum. לדוגמא, נניח שחבילה android.hardware.nfc, גרסה 1.0 מגדירה סוג enum NfcStatus :

enum NfcStatus {
    STATUS_OK,
    STATUS_FAILED
};

כאשר מתייחסים ל- STATUS_OK , השם המוסמך הוא:

android.hardware.nfc@1.0::NfcStatus:STATUS_OK

התחביר הכללי הוא PACKAGE @ VERSION :: UDT : VALUE , שם:

  • PACKAGE @ VERSION :: UDT הוא אותו שם מוסמך לחלוטין עבור סוג enum.
  • VALUE הוא שם הערך.

כללי הסקה אוטומטית

אין צורך לציין שם UDT מלא. שם UDT יכול להשמיט בבטחה את הדברים הבאים:

  • החבילה, למשל @1.0::IFoo.Type
  • גם חבילה וגם גרסה, למשל IFoo.Type

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

חוק מספר 1

אם לא מסופקים חבילה וגרסה, מנסים לחפש שם מקומי. דוגמא:

interface Nfc {
    typedef string NfcErrorMessage;
    send(NfcData d) generates (@1.0::NfcStatus s, NfcErrorMessage m);
};

NfcErrorMessage למעלה באופן מקומי, typedef שמעליו נמצא. NfcData היא הרימה גם מקומית, אבל כפי שהוא אינו מוגדר באופן מקומי, שלטון 2 ו 3 משמשים. @1.0::NfcStatus מספק גרסה, ולכן כלל 1 אינו חל.

כלל 2

אם כלל 1 נכשל ורכיב מהשם המוסמך במלואו חסר (חבילה, גרסה או חבילה וגרסה), הרכיב ממולא אוטומטית במידע מהחבילה הנוכחית. מהדר ה- HIDL מחפש בקובץ הנוכחי (ובכל הייבוא) למצוא את השם המלא במלואו. בעזרת הדוגמה לעיל, נניח שההצהרה על ExtendedNfcData נעשתה באותה חבילה ( android.hardware.nfc ) באותה גרסה ( 1.0 ) כמו NfcData , כדלקמן:

struct ExtendedNfcData {
    NfcData base;
    // … additional members
};

מהדר HIDL ממלא את שם החבילה ואת שם הגרסה מהחבילה הנוכחית כדי לייצר את שם ה- UDT המוסמך במלואו android.hardware.nfc@1.0::NfcData . מכיוון שהשם קיים בחבילה הנוכחית (בהנחה שהיא מיובאת כהלכה), הוא משמש לצורך ההצהרה.

שם בחבילה הנוכחית מיובא רק אם אחד מהדברים הבאים נכון:

  • הוא מיובא במפורש עם הצהרת import .
  • זה מוגדר ב- types.hal בחבילה הנוכחית

מתבצע אותו תהליך אם NfcData הוסמך על ידי מספר הגרסה בלבד:

struct ExtendedNfcData {
    // autofill the current package name (android.hardware.nfc)
    @1.0::NfcData base;
    // … additional members
};

כלל 3

אם כלל 2 לא מצליח לייצר התאמה (ה- UDT אינו מוגדר בחבילה הנוכחית), מהדר ה- HIDL מחפש התאמה בכל החבילות המיובאות. בעזרת הדוגמה שלעיל, נניח ש- ExtendedNfcData מוכרז בגרסה 1.1 של חבילה android.hardware.nfc , 1.1 מייבא 1.0 כפי שצריך (ראה הרחבות ברמת חבילה ), וההגדרה מציינת רק את שם ה- UDT:

struct ExtendedNfcData {
    NfcData base;
    // … additional members
};

המהדר מחפש כל UDT בשם NfcData ומוצא אחד כזה ב- android.hardware.nfc בגרסה 1.0 , וכתוצאה מכך UDT מוסמך לחלוטין של android.hardware.nfc@1.0::NfcData . אם נמצא יותר מתאמה אחת עבור UDT מוסמך חלקי, מהדר HIDL משליך.

דוגמא

באמצעות כלל 2, סוג מיובא המוגדר בחבילה הנוכחית מועדף על פני סוג מיובא מחבילה אחרת:

// hardware/interfaces/foo/1.0/types.hal
package android.hardware.foo@1.0;
struct S {};

// hardware/interfaces/foo/1.0/IFooCallback.hal
package android.hardware.foo@1.0;
interface IFooCallback {};

// hardware/interfaces/bar/1.0/types.hal
package android.hardware.bar@1.0;
typedef string S;

// hardware/interfaces/bar/1.0/IFooCallback.hal
package android.hardware.bar@1.0;
interface IFooCallback {};

// hardware/interfaces/bar/1.0/IBar.hal
package android.hardware.bar@1.0;
import android.hardware.foo@1.0;
interface IBar {
    baz1(S s); // android.hardware.bar@1.0::S
    baz2(IFooCallback s); // android.hardware.foo@1.0::IFooCallback
};
  • S משולב כ- android.hardware.bar@1.0::S ונמצא bar/1.0/types.hal (מכיוון types.hal מיובא אוטומטית).
  • IFooCallback כ- android.hardware.bar@1.0::IFooCallback באמצעות כלל 2, אך לא ניתן למצוא אותו מכיוון bar/1.0/IFooCallback.hal אינו מיובא אוטומטית (כפי types.hal הוא). לפיכך, כלל 3 פותר אותו ל- android.hardware.foo@1.0::IFooCallback במקום זאת, המיובא באמצעות import android.hardware.foo@1.0; ).

types.hal

כל חבילת HIDL מכילה קובץ types.hal המכיל UDT המשותף בין כל הממשקים המשתתפים בחבילה זו. סוגי HIDL הם תמיד ציבוריים; בין אם UDT מוכרזת types.hal או בתוך הצהרת ממשק, סוגים אלה הם לנגיש מחוץ לתחום שבו הם מוגדרים. types.hal לא נועד לתאר את ה- API הציבורי של חבילה, אלא לארח UDT שמשמש את כל הממשקים בתוך החבילה. בשל אופיו של HIDL, כל ה- UDTs הם חלק מהממשק.

types.hal מורכב מ- UDT והצהרות import . מכיוון ש- types.hal זמין לכל ממשק של החבילה (זהו ייבוא ​​משתמע), הצהרות import אלה הן ברמת החבילה בהגדרה. UDTs ב- types.hal עשויים לכלול גם UDTs וממשקים שיובאו כך.

לדוגמה, עבור IFoo.hal :

package android.hardware.foo@1.0;
// whole package import
import android.hardware.bar@1.0;
// types only import
import android.hardware.baz@1.0::types;
// partial imports
import android.hardware.qux@1.0::IQux.Quux;
// partial imports
import android.hardware.quuz@1.0::Quuz;

הבאים מיובאים:

  • android.hidl.base@1.0::IBase (במשתמע)
  • android.hardware.foo@1.0::types (מרומז)
  • הכל ב- android.hardware.bar@1.0 (כולל כל הממשקים types.hal )
  • types.hal מ- android.hardware.baz@1.0::types (ממשקים ב- android.hardware.baz@1.0 אינם מיובאים)
  • IQux.hal ו- types.hal מ- android.hardware.qux@1.0
  • Quuz מ- android.hardware.quuz@1.0 (בהנחה Quuz מוגדר ב- types.hal , כל הקובץ types.hal מנותח, אך סוגים אחרים מלבד Quuz אינם מיובאים).

גרסאות ברמת ממשק

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

package android.hardware.nfc@1.0;

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

הדוגמאות של גרסאות uprev להלן משתמשות בחבילה הבאה:

// types.hal
package android.hardware.example@1.0
struct Foo {
    struct Bar {
        vec<uint32_t> val;
    };
};

// IQuux.hal
package android.hardware.example@1.0
interface IQuux {
    fromFooToBar(Foo f) generates (Foo.Bar b);
}

חוקי Uprev

כדי להגדיר חבילה חבילה package@major.minor , A או כל B חייבים להיות נכונים:

כלל א "האם מדובר בגרסת מינור התחלה": אין package@major.0 כל הגרסאות המשניות הקודמות, package@major.0 , package@major.(minor-1) package@major.1 ,…, package@major.(minor-1) .
אוֹ
כלל ב '

כל הדברים הבאים נכונים:

  1. "הגירסה המשנית הקודמת תקפה": יש להגדיר את package@major.(minor-1) ולבצע את אותו כלל A (אף אחד מ- package@major.0 דרך package@major.(minor-2) לא מוגדר) או כלל ב '. (אם מדובר ב uprev מ- @ @major.(minor-2) );

    AND

  2. "ירש ממשק אחד לפחות עם אותו שם": קיים ממשק package@major.(minor-1)::IFoo package@major.minor::IFoo המרחיב את package@major.(minor-1)::IFoo (אם לחבילה הקודמת יש ממשק);

    AND

  3. "אין ממשק תורשתי עם שם אחר": אסור להתקיים package@major.minor::IBar המרחיב את package@major.(minor-1)::IBaz , כאשר IBar ו- IBaz הם שני שמות שונים. אם יש ממשק עם אותו שם, package@major.minor::IBar חייב להרחיב את package@major.(minor-k)::IBar כך שלא יהיה IBar עם k קטן יותר.

בגלל כלל א ':

  • החבילה יכולה להתחיל עם כל מספר גרסה מינורי (לדוגמה, android.hardware.biometrics.fingerprint מתחיל ב- @2.1 ).
  • הדרישה " android.hardware.foo@1.0 אינה מוגדרת" פירושה hardware/interfaces/foo/1.0 הספריה hardware/interfaces/foo/1.0 אפילו לא צריכה להתקיים.

עם זאת, כלל A אינו משפיע על חבילה בעלת שם חבילה זהה אלא על גרסה עיקרית שונה (לדוגמה, ל- android.hardware.camera.device מוגדרים גם @1.0 וגם @3.2 ; @3.2 לא צריך לקיים אינטראקציה עם @1.0 מכאן, @3.2::IExtFoo יכול להאריך @1.0::IFoo .

בתנאי package@major.minor::IBar החבילה שונה, package@major.minor::IBar עשוי להתרחב מממשק עם שם אחר (לדוגמה, android.hardware.bar@1.0::IBar יכול להרחיב את android.hardware.baz@2.2::IBaz ). אם ממשק אינו מצהיר במפורש על סוג סופר עם מילת המפתח extend , הוא יאריך את android.hidl.base@1.0::IBase (למעט IBase עצמו).

יש לעקוב אחר B.2 ו- B.3 במקביל. לדוגמא, גם אם android.hardware.foo@1.1::IFoo מרחיב את android.hardware.foo@1.0::IFoo כדי להעביר את כלל B.2, אם android.hardware.foo@1.1::IExtBar מרחיב את android.hardware.foo@1.0::IBar , זה עדיין לא uprev חוקי.

ממשקים מקדימים

כדי uprev android.hardware.example@1.0 (מוגדר לעיל) ל- @1.1 :

// types.hal
package android.hardware.example@1.1;
import android.hardware.example@1.0;

// IQuux.hal
package android.hardware.example@1.1
interface IQuux extends @1.0::IQuux {
    fromBarToFoo(Foo.Bar b) generates (Foo f);
}

זהו import ברמת חבילה של גרסה 1.0 של android.hardware.example ב- types.hal . אמנם לא מוסיפים שום UDT חדשים בגירסה 1.1 של החבילה, אך עדיין יש צורך בהפניות ל- UDT בגרסה 1.0 , ומכאן ייבוא ​​ברמת החבילה ב- types.hal . (ניתן היה להשיג את אותו אפקט עם ייבוא ​​ברמת הממשק ב- IQuux.hal .)

extends @1.0::IQuux בהצהרה על IQuux , ציינו את גרסת ה- IQuux בירושה (נדרשת IQuux משום IQuux משמש IQuux ממשק IQuux מממשק). מכיוון שהצהרות הן פשוט שמות שעוברות בירושה את כל מאפייני החבילה והגרסה באתר ההצהרה, על ההבהרה להיות על שם ממשק הבסיס; יכולנו להשתמש גם ב- UDT המלא, אבל זה היה מיותר.

הממשק החדש IQuux אינו IQuux מחדש על שיטה מ- fromFooToBar() שהוא יורש מ- @1.0::IQuux ; זה פשוט מפרט את השיטה החדשה שהיא מוסיפה מ- fromBarToFoo() . ב- HIDL, לא ניתן להכריז שוב על שיטות שעוברות בתורשה בממשקי הילד, ולכן ממשק IQuux אינו יכול להכריז במפורש על שיטת fromFooToBar() .

מוסכמות Uprev

לפעמים שמות ממשק חייבים לשנות את שם הממשק המרחיב. אנו ממליצים כי הרחבות, תחומים ואיגודים של enum יקבלו את אותו השם כמו שהם משתרעים אלא אם כן הם שונים דיו כדי להצדיק שם חדש. דוגמאות:

// in parent hal file
enum Brightness : uint32_t { NONE, WHITE };

// in child hal file extending the existing set with additional similar values
enum Brightness : @1.0::Brightness { AUTOMATIC };

// extending the existing set with values that require a new, more descriptive name:
enum Color : @1.0::Brightness { HW_GREEN, RAINBOW };

אם לשיטה יכולה להיות שם סמנטי חדש (למשל fooWithLocation ) אז עדיף. אחרת, יש לקרוא לזה באופן דומה למה שהוא מרחיב. לדוגמא, השיטה foo_1_1 ב- @1.1::IFoo עשויה להחליף את הפונקציונליות של שיטת foo ב- @1.0::IFoo אם אין שם חלופי טוב יותר.

גרסאות ברמת החבילה

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

עם זאת, סוג אחד של יחסים מוגדר בקפידה ויש לאכוף אותו: ירושה תואמת לאחור ברמת החבילה . בתרחיש זה, חבילת ההורה היא החבילה להיות בירושה ואת חבילת הילד היא אחד הארכת ההורה. כללי הירושה התואמים לאחור ברמת החבילה הם כדלקמן:

  1. כל הממשקים ברמה העליונה של חבילת האב עוברים בירושה מממשקים בחבילת הצאצא.
  2. ניתן להוסיף ממשקים חדשים גם את החבילה החדשה (אין הגבלות על קשרי גומלין לממשקים אחרים בחבילות אחרות).
  3. ניתן להוסיף גם סוגי נתונים חדשים לשימוש בשיטות חדשות של ממשקים קיימים שקדמו להם, או באמצעות ממשקים חדשים.

ניתן ליישם כללים אלה באמצעות תורשה ברמת ממשק HIDL והרכב UDT, אך דורשים ידע ברמת מטא בכדי לדעת שקשרים אלה מהווים סיומת חבילה תואמת לאחור. ידע זה מוסכם באופן הבא:

אם חבילה עומדת בדרישה זו, hidl-gen אוכף כללי תאימות לאחור.