HIDL

لغة تعريف واجهة HAL أو HIDL (تُنطق "hide-l") هي لغة وصف واجهة (IDL) لتحديد الواجهة بين HAL ومستخدميها. يسمح بتحديد الأنواع واستدعاءات الطريقة ، التي يتم جمعها في واجهات وحزم. على نطاق أوسع ، HIDL هو نظام للتواصل بين قواعد الرموز التي يمكن تجميعها بشكل مستقل. اعتبارًا من Android 10 ، تم إهمال HIDL وهاجر Android لاستخدام AIDL في كل مكان.

الغرض من HIDL هو استخدامه للاتصال بين العمليات (IPC). يشار الاتصال بين العمليات على أنها Binderized . للمكتبات التي يجب أن تكون مرتبطة إلى عملية، و وضع العبور متاح أيضا (غير معتمدة في جاوة).

يحدد HIDL هياكل البيانات وتوقيعات الأسلوب ، المنظمة في واجهات (على غرار الفئة) التي يتم جمعها في حزم. سيبدو بناء جملة HIDL مألوفًا لمبرمجي C ++ و Java ، على الرغم من استخدام مجموعة مختلفة من الكلمات الرئيسية. يستخدم HIDL أيضًا التعليقات التوضيحية بنمط Java.

تصميم HIDL

الهدف من HIDL هو أنه يمكن استبدال إطار العمل دون الحاجة إلى إعادة بناء HALs. وسيتم بناء طبقة تجريد من قبل البائعين أو صناع SOC وضعها في /vendor القسم على الجهاز، وتمكين الإطار، في القسم الخاص به، لتحل محلها مع OTA دون اعادة تجميع طبقة تجريد.

يوازن تصميم HIDL بين الاهتمامات التالية:

  • إمكانية التشغيل المتداخل. قم بإنشاء واجهات قابلة للتشغيل المتبادل بشكل موثوق بين العمليات التي يمكن تجميعها باستخدام العديد من البنى ، وسلاسل الأدوات ، وتكوينات البناء. تم إصدار واجهات HIDL ولا يمكن تغييرها بعد نشرها.
  • الكفاءة. يحاول HIDL تقليل عدد عمليات النسخ. يتم تسليم البيانات المعرفة بواسطة HIDL إلى كود C ++ في هياكل بيانات التخطيط القياسي C ++ التي يمكن استخدامها دون تفريغ. يوفر HIDL أيضًا واجهات ذاكرة مشتركة ، وبما أن RPCs بطيئة إلى حد ما ، فإن HIDL يدعم طريقتين لنقل البيانات دون استخدام مكالمة RPC: الذاكرة المشتركة وقائمة انتظار الرسائل السريعة (FMQ).
  • بديهية. HIDL يتجنب الشائكة قضايا ملكية الذاكرة باستخدام فقط in المعلمات لRPC (انظر الروبوت واجهة تعريف اللغة (AIDL) )؛ يتم إرجاع القيم التي لا يمكن إرجاعها بكفاءة من الطرق عبر وظائف رد الاتصال. لا يؤدي تمرير البيانات إلى HIDL لنقل أو تلقي البيانات من HIDL إلى تغيير ملكية البيانات - تظل الملكية دائمًا مع وظيفة الاستدعاء. تحتاج البيانات إلى الاستمرار فقط طوال مدة الوظيفة التي تم استدعاؤها ويمكن تدميرها على الفور بعد إرجاع الوظيفة المستدعى.

استخدام وضع العبور

لتحديث الأجهزة التي تعمل بإصدارات سابقة من Android إلى Android O ، يمكنك التفاف كل من HALs التقليدية (والقديمة) في واجهة HIDL جديدة تخدم HAL في أوضاع Bindered ونفس العملية (العبور). هذا الغلاف شفاف لكل من HAL وإطار عمل Android.

وضع العبور متاح فقط لعملاء C ++ والتطبيقات. الأجهزة التي تعمل بإصدارات سابقة من Android لا تحتوي على HALs مكتوبة بلغة Java ، لذلك فإن Java HALs مرتبطة بطبيعتها.

عندما .hal يتم ترجمة الملف، hidl-gen تنتج العبور ملف الرأس خارج BsFoo.h بالإضافة إلى رؤوس تستخدم للاتصال الموثق. هذا يعرف رأس ظائف لتكون dlopen أد. نظرًا لأن HALs العبور تعمل في نفس العملية التي يتم استدعاؤها فيها ، يتم استدعاء طرق المرور في معظم الحالات بواسطة استدعاء دالة مباشر (نفس مؤشر الترابط). oneway تشغيل الأساليب في موضوع بهم كما لا يقصد عليهم الانتظار لHAL لمعالجتها (يعني أي HAL أن الاستخدامات oneway الأساليب في وضع العبور يجب أن تكون ذات ألوان).

إعطاء IFoo.hal ، BsFoo.h يلتف الأساليب ولدت HIDL لتوفير ميزات إضافية (مثل اتخاذ oneway المعاملات تشغيل في موضوع آخر). هذا الملف هو مماثل ل BpFoo.h ، ولكن بدلا من تمرير على المكالمات IPC باستخدام الموثق، يتم استدعاء مباشرة المهام المطلوبة. قد توفر تطبيقات المستقبلية هالس تطبيقات متعددة، مثل 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 إد وإنشاء مثيل تنفيذ باستخدام 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.
  • تفصل الفواصل عن عناصر التسلسل.
  • تنهي الفاصلة المنقوطة كل عنصر ، بما في ذلك العنصر الأخير.
  • الأحرف الكبيرة هي علامة غير نهائية.
  • 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 لاستدعاءات الإجراءات عن بُعد بين العمليات ، والتي يتم تنفيذها عبر آلية تشبه Binder. انظر أيضا العبور.
رد الاتصال غير متزامن واجهة يخدمها مستخدم HAL ، تم تمريرها إلى HAL (عبر طريقة HIDL) ، ويتم استدعاؤها بواسطة HAL لإرجاع البيانات في أي وقت.
رد اتصال متزامن إرجاع البيانات من تطبيق أسلوب HIDL الخاص بالخادم إلى العميل. غير مستخدمة للطرق التي تُرجع باطلة أو قيمة أولية واحدة.
زبون العملية التي تستدعي طرق واجهة معينة. قد تكون عملية HAL أو إطار العمل عميلاً لواجهة واحدة وخادم آخر. انظر أيضا العبور.
يمتد يشير إلى واجهة تضيف أساليب و / أو أنواعًا إلى واجهة أخرى. يمكن للواجهة توسيع واجهة واحدة أخرى فقط. يمكن استخدامه لزيادة إصدار ثانوي في نفس اسم الحزمة أو لحزمة جديدة (مثل امتداد البائع) للبناء على حزمة قديمة.
يولد يشير إلى طريقة واجهة تقوم بإرجاع القيم إلى العميل. لإرجاع قيمة واحدة غير أولية ، أو أكثر من قيمة واحدة ، يتم إنشاء وظيفة رد اتصال متزامن.
واجهه المستخدم مجموعة من الأساليب والأنواع. تُترجم إلى فصل دراسي بلغة C ++ أو Java. يتم استدعاء جميع الطرق في الواجهة في نفس الاتجاه: تستدعي عملية العميل الطرق التي تنفذها عملية الخادم.
اتجاه واحد عند تطبيقه على طريقة HIDL ، يشير إلى أن الطريقة لا تُرجع أي قيم ولا تمنع.
صفقة مجموعة من الواجهات وأنواع البيانات التي تشترك في إصدار.
يمر من خلال طريقة HIDL الذي كان الملقم مكتبة مشتركة، dlopen بقلم العميل. في وضع العبور ، يكون العميل والخادم نفس العملية لكنهما مصدران منفصلان. تستخدم فقط لإحضار قواعد الرموز القديمة في نموذج HIDL. انظر Binderized أيضا.
الخادم العملية التي تنفذ أساليب الواجهة. انظر أيضا العبور.
المواصلات البنية التحتية HIDL التي تنقل البيانات بين الخادم والعميل.
إصدار نسخة الحزمة. يتكون من عددين صحيحين ، كبير وثانوي. قد تضيف الزيادات الطفيفة في الإصدارات (ولكن لا تغير) الأنواع والطرق.