HIDL

שפת הגדרת ממשק HAL או HIDL (מבוטא "להסתיר- l") היא שפת תיאור ממשק (IDL) לציון הממשק בין HAL לבין משתמשיה. הוא מאפשר ציון סוגים ושיחות שיטה, שנאספו בממשקים וחבילות. באופן רחב יותר, HIDL היא מערכת לתקשורת בין בסיסי קוד שניתן להרכיב באופן עצמאי. החל מאנדרואיד 10, HIDL הוצא משימוש ואנדרואיד נודדת לשימוש ב- AIDL בכל מקום.

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

HIDL מציין מבני נתונים וחתימות שיטות, המאורגנים בממשקים (בדומה למחלקה) הנאספים לחבילות. התחביר של HIDL ייראה מוכר למתכנתים C ++ ו- Java, אם כי עם קבוצה אחרת של מילות מפתח. HIDL משתמשת גם בהערות בסגנון ג'אווה.

עיצוב HIDL

מטרת HIDL היא שניתן להחליף את המסגרת ללא צורך לבנות מחדש HALs. שכבות HAL ייבנה על ידי ספקים או מקבלי SOC ולשים /vendor מחיצה במכשיר, מה שמאפשר את המסגרת, במחיצה משלה, כדי להיות מוחלף עם OTA בלי recompiling האלס.

עיצוב HIDL מאזן את החששות הבאים:

  • יכולת פעולה הדדית. צור ממשקים הניתנים להדפסה מהימנים בין תהליכים הניתנים להידור עם ארכיטקטורות, רשתות כלים ותצורות שונות. ממשקי HIDL הינם בגירסאות ואינם ניתנים לשינוי לאחר פרסומם.
  • יעיל. HIDL מנסה למזער את מספר פעולות ההעתקה. נתונים המוגדרים על ידי HIDL מועברים לקוד C ++ במבני נתוני פריסה סטנדרטיים של C ++, שניתן להשתמש בהם ללא פירוק. HIDL מספקת גם ממשקי זיכרון משותפים, ומאחר ש- RPC הם מטבעם איטיים במקצת, HIDL תומך בשתי דרכים להעברת נתונים מבלי להשתמש בשיחת RPC: זיכרון משותף ותור הודעות מהירות (FMQ).
  • אינטואיטיבי. HIDL נמנע קוצני סוגיות בעלות זיכרון באמצעות רק in פרמטרים עבור RPC (ראה הגדרה של ממשק אנדרואיד שפה (AIDL) ); ערכים שלא ניתן להחזיר ביעילות משיטות מוחזרים באמצעות פונקציות החזרה. אי העברת נתונים ל- HIDL לצורך העברה או קבלת נתונים מ- HIDL משנה את הבעלות על הנתונים - הבעלות נשארת תמיד עם הפונקציה המתקשרת. הנתונים צריכים להימשך רק למשך הפונקציה הנקראת ועשויים להיהרס מיד לאחר החזרה של הפונקציה הנקראת.

שימוש במצב מעבר

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

מצב Passthrough זמין רק עבור לקוחות C ++ והטמעה. למכשירים שבהם פועל גירסאות קודמות של אנדרואיד אין כתבי HAL כתובים ב- Java, כך ש- HALs של Java מאוגדים מטבעם.

כאשר .hal קובץ נערך, hidl-gen יוצרת קובץ כותרת תמסורת תוספת BsFoo.h בנוסף הכותרות המשמשות לתקשורת קלסר; פונקציות מגדיר את הכותרת הזו כדי להיות dlopen ed. כאשר HALs של מעבר דרך פועלים באותו תהליך שבו הם נקראים, ברוב המקרים שיטות מעבר עוברות על ידי שיחת פונקציה ישירה (אותו חוט). oneway שיטות לרוץ חוט שלהם כפי שהם אינם מיועדים לחכות HAL לעבד אותם (אמצעי זה כל HAL כי השימושים oneway שיטות במצב התמסורת חייב להיות חוט בטוח).

בהינתן IFoo.hal , BsFoo.h עוטפת את השיטות שנוצר HIDL לספק תכונות נוספות (כגון ביצוע oneway עסקאות לרוץ חוט אחר). קובץ זה דומה BpFoo.h , אולם במקום להעביר שיחות IPC באמצעות קלסר, את הפונקציות רצוי מופעלות ישירות. מימושים עתידיים של שכבות HAL עשויים לספק יישומים מרובים, כגון FooFast HAL ו HAL FooAccurate. במקרים כאלה, קובץ עבור כול יישום נוסף ייוצר (למשל, PTFooFast.cpp ו PTFooAccurate.cpp ).

מחמירים מעבר ל HALs

אתה יכול לאגד יישומי HAL התומכים במצב מעבר. בהינתן HAL ממשק abcd@MN::IFoo , שתי חבילות נוצרות:

  • abcd@MN::IFoo-impl . מכיל יישום HAL וחושפת לתפקד IFoo* HIDL_FETCH_IFoo(const char* name) . במכשירים עם מורשתו, את החבילה הזו היא dlopen ed ואת היישום הוא מופעים באמצעות HIDL_FETCH_IFoo . אתה יכול ליצור את קוד הבסיס באמצעות hidl-gen ו -Lc++-impl ו -Landroidbp-impl .
  • abcd@MN::IFoo-service . פותח את HAL של מעבר הרשום ומרשם את עצמו כשירות מאוגדר, ומאפשר את אותו יישום HAL לשימוש גם כמעבר וגם כמסוגר.

בהתחשב בסוג IFoo , אתה יכול להתקשר sp<IFoo> IFoo::getService(string name, bool getStub) כדי לקבל גישה מופע של IFoo . אם getStub נכון, getService ניסיונות לפתוח את HAL רק במצב התמסורת. אם getStub היא שקרית, getService ניסיונות למצוא שירות binderized; אם זה נכשל, הוא מנסה למצוא את שירות המעבר. getStub פרמטר לא צריך להיות בשימוש למעט defaultPassthroughServiceImplementation . (התקנים שמפעילים עם Android O הם מכשירים מאוגדים במלואם, כך שאסור לפתוח שירות במצב מעבר.)

דקדוק HIDL

לפי העיצוב, שפת HIDL דומה ל- C (אך אינה משתמשת במעבדה קדם C). כל סימני הפיסוק לא המתוארות להלן (מלבד השימוש הברור של = ו | ) הוא חלק הדקדוק.

הערה: לפרטים על סגנון קוד HIDL, לראות את מדריך סגנון קוד .

  • /** */ מציין תגובת תיעוד. ניתן ליישם אותם רק על הצהרות ערך, סוג, שיטה, שדה והערך.
  • /* */ מציין תגובה מרובה.
  • // מצביע תגובה עד סוף השורה. מלבד // , בשורות חדשות זהות בכול רווחים אחרים.
  • בדקדוק בדוגמה הבאה, טקסט מתוך // עד הסוף של הקו הוא לא חלק הדקדוק אבל הוא למעשה הערה על דקדוק.
  • [empty] הוא שהמונח יכול להיות ריק.
  • ? אחרי מילולית או מונח פירושו שזה אופציונלי.
  • ... מציין רצף המכיל אפס או יותר פריטים עם הפרדת פיסוק כמצוין. אין טיעונים משתנים ב- HIDL.
  • פסיקים מפרידים בין רכיבי רצף.
  • נקודה -פסיק מסיימים כל אלמנט, כולל האלמנט האחרון.
  • UPPERCASE הוא לא סופי.
  • italics הוא אסימון המשפחה כגון integer או identifier (כללים ניתוח C סטנדרטי).
  • constexpr הוא ביטוי מתמיד בסגנון C (כגון 1 + 1 ו 1L << 3 ).
  • import_name הוא שם החבילה או ממשק, מוסמך כמתואר HIDL גרסאות .
  • אותיות קטנות words הן אסימונים מילוליים.

דוגמא:

ROOT =
    PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... }  // not for types.hal
  | PACKAGE IMPORTS ITEM ITEM...  // only for types.hal; no method definitions

ITEM =
    ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES?;
  |  safe_union identifier { UFIELD; UFIELD; ...};
  |  struct identifier { SFIELD; SFIELD; ...};  // Note - no forward declarations
  |  union identifier { UFIELD; UFIELD; ...};
  |  enum identifier: TYPE { ENUM_ENTRY, ENUM_ENTRY ... }; // TYPE = enum or scalar
  |  typedef TYPE identifier;

VERSION = integer.integer;

PACKAGE = package android.hardware.identifier[.identifier[...]]@VERSION;

PREAMBLE = interface identifier EXTENDS

EXTENDS = <empty> | extends import_name  // must be interface, not package

GENERATES = generates (FIELD, FIELD ...)

// allows the Binder interface to be used as a type
// (similar to typedef'ing the final identifier)
IMPORTS =
   [empty]
  |  IMPORTS import import_name;

TYPE =
  uint8_t | int8_t | uint16_t | int16_t | uint32_t | int32_t | uint64_t | int64_t |
 float | double | bool | string
|  identifier  // must be defined as a typedef, struct, union, enum or import
               // including those defined later in the file
|  memory
|  pointer
|  vec<TYPE>
|  bitfield<TYPE>  // TYPE is user-defined enum
|  fmq_sync<TYPE>
|  fmq_unsync<TYPE>
|  TYPE[SIZE]

FIELD =
   TYPE identifier

UFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...};
  |  struct identifier { FIELD; FIELD; ...};
  |  union identifier { FIELD; FIELD; ...};
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SIZE =  // Must be greater than zero
     constexpr

ANNOTATIONS =
     [empty]
  |  ANNOTATIONS ANNOTATION

ANNOTATION =
  |  @identifier
  |  @identifier(VALUE)
  |  @identifier(ANNO_ENTRY, ANNO_ENTRY  ...)

ANNO_ENTRY =
     identifier=VALUE

VALUE =
     "any text including \" and other escapes"
  |  constexpr
  |  {VALUE, VALUE ...}  // only in annotations

ENUM_ENTRY =
     identifier
  |  identifier = constexpr

טרמינולוגיה

סעיף זה משתמש במונחים הבאים הקשורים ל- HIDL:

מאוגד מציין כי HIDL משמש לשיחות הליך מרוחקות בין תהליכים, המיושמות באמצעות מנגנון דמוי קלסר. ראה גם תמסורת.
התקשרות חזרה, אסינכרונית ממשק המוגש על ידי משתמש HAL, הועבר ל- HAL (באמצעות שיטת HIDL), וקרא על ידי ה- HAL להחזיר נתונים בכל עת.
התקשרות חזרה, סינכרוני מחזירה נתונים מיישום שיטת HIDL של שרת ללקוח. לא בשימוש בשיטות שמחזירות חלל או ערך פרימיטיבי יחיד.
לָקוּחַ תהליך המכנה שיטות של ממשק מסוים. תהליך HAL או תהליך מסגרת עשוי להיות לקוח של ממשק אחד ושרת של אחר. ראה גם תמסורת.
משתרע מציין ממשק המוסיף שיטות ו/או סוגים לממשק אחר. ממשק יכול להרחיב רק ממשק אחד אחר. יכול לשמש להוספת גרסה משנית באותו שם חבילה או לחבילה חדשה (למשל הרחבת ספק) לבנייה על חבילה ישנה יותר.
מייצר מציין שיטת ממשק המחזירה ללקוח ערכים. כדי להחזיר ערך אחד לא פרימיטיבי, או יותר מערך אחד, נוצרת פונקציית התקשרות סינכרונית.
מִמְשָׁק אוסף שיטות וסוגים. תורגם לשיעור ב- C ++ או ב- Java. כל השיטות בממשק נקראות באותו כיוון: תהליך לקוח מפעיל שיטות המיושמות על ידי תהליך שרת.
דרך אחת כאשר היא מיושמת על שיטת HIDL, מציינת שהשיטה לא מחזירה ערכים ואינה חוסמת.
חֲבִילָה אוסף ממשקים וסוגי נתונים המשתפים גרסה.
עובר דרך מצב של HIDL שבו השרת היא ספריה משותפת, dlopen ed ידי הלקוח. במצב מעבר, לקוח ושרת הם אותו תהליך אך בסיסי קוד נפרדים. משמש רק להבאת בסיסי קוד מדור קודם לדגם HIDL. ראו גם Binderized.
שרת תהליך המיישם שיטות של ממשק. ראה גם תמסורת.
תַחְבּוּרָה תשתית HIDL המעבירה נתונים בין השרת ללקוח.
גִרְסָה גרסה של חבילה. מורכב משני מספרים שלמים, גדולים וקטנים. תוספות גרסה קטנות עשויות להוסיף (אך לא לשנות) סוגים ושיטות.