میانه‌ها و بسته‌ها

‫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();
};

میانایی بدون extends اعلانی صریح به‌طور ضمنی از android.hidl.base@1.0::IBase گسترش می‌یابد (مشابه java.lang.Object در جاوا). واسط IBase که به‌طور ضمنی وارد شده است، چندین روش رزروشده را تعریف می‌کند که نباید و نمی‌تواند در واسط‌های تعریف‌شده توسط کاربر دوباره تعریف شود یا به روش دیگری استفاده شود. این روش‌ها شامل موارد زیر می‌شود:

  • ping
  • interfaceChain
  • interfaceDescriptor
  • notifySyspropsChanged
  • linkToDeath
  • unlinkToDeath
  • setHALInstrumentation
  • getDebugInfo
  • debug
  • getHashChain

فرایند وارد کردن

عبارت import سازوکار HIDL برای دسترسی به میان‌ها و انواع بسته دیگر است. بیانیه import به دو نهاد مربوط می‌شود:

  • نهاد واردکننده که می‌تواند بسته یا میانای باشد
  • نهاد واردشده، که می‌تواند بسته یا واسط باشد

نهاد واردکننده براساس مکان عبارت import تعیین می‌شود. وقتی عبارت داخل types.hal بسته باشد، آنچه وارد می‌شود برای کل بسته قابل‌مشاهده است؛ این وارد کردن در سطح بسته است. وقتی بیانیه در فایل واسط باشد، نهاد واردکننده خود واسط است؛ این یک وارد کردن سطح واسط است.

نهاد واردشده براساس مقدار پس‌از import کلیدواژه تعیین می‌شود. مقدار لازم نیست نام کاملاً واجدشرایط باشد؛ اگر مؤلفه‌ای حذف شود، به‌طور خودکار با اطلاعات بسته فعلی تکمیل می‌شود. برای مقادیر کاملاً واجدشرایط، موارد وارد کردن زیر پشتیبانی می‌شوند:

  • وارد کردن کل بسته. اگر مقدار نام بسته و نسخه باشد (نحو در زیر توضیح داده شده است)، کل بسته به نهاد واردکننده وارد می‌شود.
  • وارد کردن جزئی. اگر مقدار:
    • میانایی، types.hal بسته، و آن میانایی به نهاد واردکننده وارد می‌شوند.
    • یک UDT در types.hal تعریف شده است، سپس فقط آن UDT به نهاد واردکننده وارد می‌شود (انواع دیگر در types.hal وارد نمی‌شوند).
  • وارد کردن فقط انواع. اگر مقدار از دستور زبان وارد کردن جزئی که در بالا توضیح داده شده است استفاده کند، اما با کلیدواژه types به‌جای نام «میانای» (Interface)، فقط «انواع داده تعریف‌شده توسط کاربر» در types.hal بسته تعیین‌شده وارد می‌شود.

نهاد واردکننده به ترکیبی از موارد زیر دسترسی پیدا می‌کند:

  • UDTهای مشترک بسته واردشده در 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

وراثت میانا

میان‌گیری می‌تواند گسترش میان‌گیری ازپیش تعریف‌شده باشد. افزونه‌ها می‌توانند یکی از سه نوع زیر باشند:

  • میانای می‌تواند با ترکیب کردن API بدون تغییر، به میانای دیگر قابلیت اضافه کند.
  • بسته می‌تواند با گنجاندن API خود بدون تغییر، به بسته دیگری قابلیت اضافه کند.
  • میانای کاربری می‌تواند انواع را از یک بسته یا از یک میانای کاربری خاص وارد کند.

یک میانای می‌تواند فقط یک میانای دیگر را گسترش دهد (بدون وراثت چندگانه). هر میانای موجود در بسته‌ای با شماره نسخه جزئی غیرصفر باید میانایی را در نسخه قبلی بسته گسترش دهد. برای مثال، اگر میانایی IBar در نسخه ۴٫۰ بسته derivative براساس (گسترش) میانایی IFoo در نسخه ۱٫۲ بسته original باشد، و نسخه ۱٫۳ بسته original ایجاد شود، نسخه ۴٫۱ IBar نمی‌تواند نسخه ۱٫۳ IFoo را گسترش دهد. درعوض، IBar نسخه ۴.۱ باید IBar نسخه ۴.۰ را گسترش دهد که به IFoo نسخه ۱.۲ مرتبط است. درصورت تمایل، IBar نسخه ۵.۰ می‌تواند IFoo نسخه ۱.۳ را گسترش دهد.

افزونه‌های میانای کاربری به معنای وابستگی به کتابخانه یا گنجاندن میان‌HAL در کد تولیدشده نیستند—آن‌ها صرفاً ساختار داده و تعاریف روش را در سطح HIDL وارد می‌کنند. همه روش‌های موجود در یک HAL باید در همان HAL پیاده‌سازی شوند.

افزونه‌های فروشنده

در برخی موارد، افزونه‌های فروشنده به‌عنوان زیرکلاس شیء پایه پیاده‌سازی می‌شوند که نشان‌دهنده میانای اصلی است که آن‌ها گسترش می‌دهند. همان شیء تحت نام و نسخه HAL پایه و تحت نام و نسخه HAL (فروشنده) افزونه ثبت شده است.

نسخه‌بندی

بسته‌ها دارای نسخه هستند و واسط‌ها نسخه بسته خود را دارند. نسخه‌ها به‌صورت دو عدد صحیح، عمده.جزئی، بیان می‌شوند.

  • نسخه‌های اصلی با نسخه‌های قدیمی سازگار نیستند. افزایش شماره نسخه اصلی باعث می‌شود شماره نسخه جزئی به ۰ بازنشانی شود.
  • نسخه‌های جزئی با نسخه‌های قدیمی سازگار هستند. افزایش عدد جزئی نشان می‌دهد که نسخه جدیدتر کاملاً با نسخه قبلی سازگار با نسخه قدیمی است. ساختارها و روش‌های داده جدید را می‌توان اضافه کرد، اما هیچ‌کدام از ساختارها یا امضاهای روش داده موجود را نمی‌توان تغییر داد.

چندین نسخه اصلی یا فرعی از یک 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 بحث شده است).

میان‌ها در مکان‌های مستقل از دستگاه قرار می‌گیرند

در عمل، توصیه می‌کنیم واسط‌ها را بین شاخه‌ها هم‌رسانی کنید. این امر امکان استفاده مجدد حداکثری از کد و آزمایش حداکثری کد را در دستگاه‌ها و موارد استفاده مختلف فراهم می‌کند.