تم إنشاء HIDL حول الواجهات، وهي نوع تجريدي يستخدم في اللغات كائنية التوجيه لتحديد السلوكيات. كل واجهة هي جزء من حزمة.
إدارة الحِزم
يمكن أن تحتوي أسماء الحِزم على مستويات فرعية، مثل package.subpackage
. ملف تعريف الدليل الجذر لحِزم HIDL المنشورة هو hardware/interfaces
أو vendor/vendorName
(على سبيل المثال، vendor/google
لأجهزة Pixel
). يشكّل اسم الحزمة دليلاً فرعيًا واحدًا أو أكثر ضمن الدليل العميق، وتكون جميع الملفات التي تحدّد الحزمة في الدليل نفسه. على سبيل المثال، يمكن العثور على
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/* |
أُطر عمل/ ذات صلة |
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(); };
تمتد الواجهة بشكل ضمني
من android.hidl.base@1.0::IBase
(على غرار
java.lang.Object
في Java) إذا لم يتم تضمين بيان extends
صريح لها. واجهة IBase التي يتم استيرادها بشكل ضمني تعلن عن عدة طرق محجوزة لا يجب ولا يمكن
إعادة إعلانها في الواجهات التي يحدّدها المستخدم أو استخدامها بأي شكل آخر. وتشمل هذه الطرق
ما يلي:
ping
interfaceChain
interfaceDescriptor
notifySyspropsChanged
linkToDeath
unlinkToDeath
setHALInstrumentation
getDebugInfo
debug
getHashChain
عملية الاستيراد
عبارة import
هي آلية HIDL للوصول إلى واجهة
الحزمة وأنواعها في حزمة أخرى. تتناول عبارة import
كيانَين:
- عنصر الاستيراد، الذي يمكن أن يكون حزمة أو واجهة
- الكيانالمستورَد، والذي يمكن أن يكون حزمة أو واجهة
يتم تحديد الكيان المستورِد حسب موضع بيان
import
. عندما يكون البيان داخل types.hal
الحزمة، يكون ما يتم استيراده مرئيًا للحزمة بأكملها، ويُعدّ ذلك استيرادًا على مستوى الحزمة. عندما يكون البيان داخل ملف
واجهة، يكون الكيان المستورِد هو الواجهة نفسها، وهذا هو استيراد
على مستوى الواجهة.
يتم تحديد الكيان المستورَد من خلال القيمة التي تأتي بعد الكلمة الرئيسية import
. ولا يلزم أن تكون القيمة اسمًا مؤهَّلاً بالكامل. وفي حال حذف أحد المكوّنات، يتم ملؤه تلقائيًا بمعلومات من الحزمة الحالية.
بالنسبة إلى القيم المؤهَّلة بالكامل، تكون حالات الاستيراد التالية متاحة:
- عمليات استيراد الحِزم بأكملها: إذا كانت القيمة هي اسم حزمة و إصدار (البنية النحوية الموضّحة أدناه)، يتم استيراد الحزمة بأكملها إلى العنصر المستورِد.
- عمليات الاستيراد الجزئية: إذا كانت القيمة:
- يتم استيراد واجهة و
types.hal
الحزمة وتلك الواجهة إلى الكيان المستورِد. - عنصر بيانات مستخدم محدّد في
types.hal
، ثم يتم استيراد عنصر البيانات المستخدَم هذا فقط إلى العنصر المستورِد (لا يتم استيراد الأنواع الأخرى فيtypes.hal
).
- يتم استيراد واجهة و
- عمليات الاستيراد التي تتضمّن الأنواع فقط: إذا كانت القيمة تستخدِم بنية العبارة الخاصة بالاستيراد الجزئي الموضّحة أعلاه، ولكن باستخدام الكلمة الرئيسية
types
بدلاً من اسم واجهة، لا يتم استيراد سوى أنواع البيانات الوصفية فيtypes.hal
من الحزمة المخصّصة.
يحصل الكيان المستورِد على مجموعة من:
- وحدات البيانات الوصفية الشائعة للحزمة المستورَدة والمُحدَّدة في
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
اكتساب الأذونات من الواجهات
يمكن أن تكون الواجهة امتدادًا لواجهة محدّدة مسبقًا. يمكن أن تكون الإضافات من أحد الأنواع الثلاثة التالية:
- يمكن أن تضيف الواجهة وظيفة إلى واجهة أخرى، مع دمج واجهة برمجة التطبيقات بدون تغيير.
- يمكن أن تضيف الحزمة وظيفة إلى حزمة أخرى، مع دمج واجهة برمجة التطبيقات بدون تغيير.
- يمكن للواجهة استيراد الأنواع من حزمة أو من واجهة معيّنة.
يمكن للواجهة أن تمتد إلى واجهة أخرى واحدة فقط (لا يمكن اكتساب سمات متعددة).
يجب أن تُنشئ كل واجهة في حزمة ذات رقم إصدار ثانوي غير صفري واجهة في الإصدار السابق من الحزمة. على سبيل المثال، إذا كانت الواجهة
IBar
في الإصدار 4.0 من الحزمة derivative
تستند إلى
(توسّع) واجهة IFoo
في الإصدار 1.2 من الحزمة
original
، وتم إنشاء الإصدار 1.3 من الحزمة original
،
لا يمكن للإصدار 4.1 من IBar
توسيع الإصدار 1.3 من
IFoo
. بدلاً من ذلك، يجب أن يمتد إصدار IBar
4.1
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 بشكل عام، والتعريفات التالية:
العبارة | التعريف |
---|---|
واجهة التطبيق الثنائية (ABI) | واجهة برمجة التطبيقات بالإضافة إلى أي روابط ثنائية مطلوبة |
الاسم المؤهَّل بالكامل (fqName) | اسم لتمييز نوع hidl مثال:
android.hardware.foo@1.0::IFoo |
طرد | حزمة تحتوي على واجهة HIDL وأنواعها مثال:
android.hardware.foo@1.0 |
جذر الحزمة | الحزمة الجذر التي تحتوي على واجهات HIDL مثال: واجهة HIDL
android.hardware في جذر الحزمة
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
.
من الناحية العملية، ننصح المورّد أو المصنّع الأصلي للجهاز الذي يحمل الاسم 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).
توضع الواجهات في مواضع مستقلة عن الجهاز .
من الناحية العملية، ننصحك بمشاركة الواجهات بين الفروع. ويتيح ذلك أقصى قدر من إعادة استخدام الرمز البرمجي وأقصى قدر من اختباره على مختلف الأجهزة وحالات الاستخدام.