مؤسسة HIDL

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

تم تصميم HIDL للاتصال بين العمليات (IPC). تُعد HALs التي يتم إنشاؤها باستخدام HDL تسمى HALs من حيث قدرتها على التواصل مع طبقات بنية أخرى باستخدام البيندر مكالمات الاتصال بين العمليات (IPC). يتم تشغيل HALs المُدمجة في عملية منفصلة عن العميل. التي تستخدمها. بالنسبة المكتبات التي يجب ربطها بعملية ما أو عبور الوضع متاح أيضًا (غير متاح في Java).

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

المصطلحات

يستخدم هذا القسم العبارات التالية المتعلّقة بشهادة HIDL:

دمج يشير إلى استخدام HIDL في استدعاء الإجراءات عن بُعد بين العمليات، باستخدام آلية تشبه الصنفرة. اطّلِع أيضًا على المرور.
رد الاتصال، غير متزامن واجهة يعرضها مستخدم HAL، ويتم تمريرها إلى HAL (باستخدام طريقة HIDL) بواسطة HAL لعرض البيانات في أي وقت.
معاودة الاتصال، متزامن تعرض البيانات من تنفيذ طريقة HIDL للخادم إلى العميل. ولا يُستخدم للطرق التي تعرض قيمة فارغة أو قيمة أساسية واحدة.
عميل العملية التي تستدعي طرقًا لواجهة معينة. إطار عمل Android أو HAL قد تكون العملية العميلة لواجهة واحدة وخادمًا لواجهة أخرى. يمكن أيضًا مراجعة
يمتد يشير إلى الواجهة التي تضيف طرقًا و/أو أنواعًا إلى واجهة أخرى. يمكن للواجهة تمديد واجهة واحدة أخرى فقط. يمكن استخدامه للقاصرين في الإصدار نفسه باسم الحزمة نفسها أو لحزمة جديدة (مثل مورّد الإضافة) للبناء على حزمة أقدم.
يُنشئ يشير إلى طريقة واجهة تعرض قيمًا للعميل. للإرجاع أو قيمة واحدة غير أولية أو أكثر من قيمة واحدة، وهي دالة استدعاء متزامنة يتم إنشاء خوارزمية تحليل البيانات.
واحدة مجموعة الطرق والأنواع. إذا تمت ترجمتها إلى صف باستخدام لغة C++ أو Java. الكل يتم استدعاء الطرق الموجودة في الواجهة بنفس الاتجاه: عملية العميل استدعاء طرق تنفذها عملية الخادم.
ذهاب فقط عند تطبيقها على طريقة HIDL، فإنها تشير إلى أن الطريقة لا تقوم بإرجاع أي قيم لا يحظر.
طرد مجموعة من الواجهات وأنواع البيانات تتشارك إصدارًا.
تقنية مرور الإشارة وضع HIDL الذي يكون فيه الخادم مكتبة مشتركة، dlopen من جانب العميل. في وضع العبور، يكون العميل والخادم نفس العملية ولكن قواعد رموز منفصلة. يُستخدم فقط لإدخال قواعد الرموز القديمة في نموذج HIDL. راجِع أيضًا المقالة مدمجة.
خادم يشير ذلك المصطلح إلى عملية يتم فيها تنفيذ طرق الواجهة. يمكن أيضًا مراجعة
وسيلة مواصلات بنية HIDL الأساسية التي تنقل البيانات بين الخادم والعميل.
إصدار إصدار الحزمة. تتكوّن من عددين صحيحين، كبير وثانوي. قاصر قد تضيف زيادات الإصدارات أنواعًا وطرقًا (بدون تغييرها).

تصميم HIDL

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

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

  • إمكانية التشغيل التفاعلي: إنشاء واجهات قابلة للتشغيل التفاعلي بشكلٍ موثوق بين العمليات التي يمكن تجميعها باستخدام العديد من البنى وسلاسل الأدوات وإنشاء التكوينات. تم تحديد إصدارات من واجهات HIDL ولا يمكن تغييرها. بعد نشرها.
  • الكفاءة: يحاول HIDL تقليل عدد النُسخ operations. يتم تسليم بيانات HIDL المحددة إلى رمز C++ بتنسيق C++ القياسي وهياكل البيانات التي يمكن استخدامها دون فك الضغط. يوفر HIDL أيضًا ميزات لواجهات الذاكرة، وبما أنّ استدعاء الدوال البرمجية بطيئة إ��ى حدّ ما، فإنّ HIDL يدعم اثنين طرق لنقل البيانات بدون استخدام استدعاء إجراء عن بُعد (RPC): ذاكرة مشتركة وواجهة قائمة انتظار الرسائل (FMQ)
  • سهلة الاستخدام: تتجنب HIDL المشكلات الشائكة المتعلقة بملكية الذاكرة من خلال باستخدام مَعلمات in فقط لمتوسط عائد النقرة (راجع نظام التشغيل Android لغة تعريف الواجهة (AIDL)) قيم لا يمكن تشغيلها بكفاءة التي يتم إرجاعها من الطرق عبر دوال الاستدعاء. لا يتم تمرير البيانات إلى HIDL لنقل أو تلقي البيانات من HIDL لملكية البيانات — تظل الملكية دائمًا مع دالة الاستدعاء. تحتاج البيانات إلى: تستمر فقط طوال مدة الدالة المطلوبة وقد تتعرض للتلف مباشرةً بعد رجوع الدالة المطلوبة.

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

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

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

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

بناءً على IFoo.hal، يلتقي BsFoo.h بالمادة التي تم إنشاؤها من خلال HIDL. لتوفير ميزات إضافية (مثل إنشاء oneway التي يتم إجراؤها في سلسلة محادثات أخرى). يشبه هذا الملف BpFoo.h، ومع ذلك بدلاً من إرسال الاتصال بـ IPC باستخدام أمر الربط، يتم عرض يتم استدعاء الدوال المطلوبة مباشرة. عمليات التنفيذ المستقبلية لHALs قد توفر عمليات تنفيذ متعددة، مثل FooFast HAL FooMetric HAL. في هذه الحالات، سيكون ملف لكل عملية تنفيذ إضافية أن يتم إنشاؤه (على سبيل المثال، PTFooFast.cpp و PTFooAccurate.cpp).

ربط HALs للمرور

يمكنك دمج عمليات تنفيذ HAL التي تدعم وضع العبور. استنادًا إلى واجهة HAL a.b.c.d@M.N::IFoo، تمّ إنشاء حزمتَين:

  • a.b.c.d@M.N::IFoo-impl يحتوي على تنفيذ اتفاقية HAL ويعرض الدالة IFoo* HIDL_FETCH_IFoo(const char* name). مشغَّلة على الأجهزة القديمة، تم dlopenإعداد هذه الحزمة وتنفيذها تم إنشاء مثيل باستخدام HIDL_FETCH_IFoo. يمكنك إنشاء الرمز الأساسي باستخدام hidl-gen و-Lc++-impl -Landroidbp-impl
  • a.b.c.d@M.N::IFoo-service يفتح HAL العبور تسجل نفسها كخدمة ثنائية، تتيح تنفيذ نفس بروتوكول HAL للاستخدام كعبور ودمج.

بالنسبة إلى النوع IFoo، يمكنك الاتصال بـ sp<IFoo> IFoo::getService(string name, bool getStub) للوصول إلى أحد الأجهزة الافتراضية. من IFoo. إذا كانت getStub صحيحة، getService فتح بروتوكول HAL فقط في وضع العبور. إذا كانت السمة getStub خطأ، يحاول getService العثور على خدمة ثنائية الهوية. إذا كان ذلك فإنه يحاول العثور على خدمة العبور. 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