ایجاد میانای HAL

باید از HIDL برای توصیف همه پرچم‌های ساختمانی که برای گردآوری مشروط چارچوب استفاده می‌شود استفاده کنید. پرچم‌های ساخت مربوطه باید گروه‌بندی شوند و در یک فایل .hal گنجانده شوند. استفاده از HIDL برای مشخص کردن موارد پیکربندی مزایای زیر را دارد:

  • نسخه‌بندی‌شده (برای افزودن عناصر پیکربندی جدید، فروشندگان/تولیدکنندگان تجهیزات اصلی باید به‌طور صریح «لایه انتزاع سخت‌افزار» را گسترش دهند)
  • مستندسازی خوب
  • کنترل دسترسی بااستفاده از SELinux
  • بررسی منطقی موارد پیکربندی ازطریق مجموعه آزمایش فروشنده (بررسی محدوده، بررسی وابستگی متقابل بین موارد، و غیره)
  • میاناهای برنامه‌سازی کاربردی تولیدشده به‌صورت خودکار در C++ و Java

شناسایی پرچم‌های ساخت استفاده‌شده توسط چارچوب

با شناسایی پیکربندی‌های ساختمانی که برای کامپایل مشروط چارچوب استفاده می‌شوند شروع کنید، سپس پیکربندی‌های منسوخ را کنار بگذارید تا مجموعه کوچک‌تر شود. برای مثال، مجموعه پرچم‌های ساخت زیر برای surfaceflinger شناسایی شده است:

  • TARGET_USES_HWC2
  • TARGET_BOARD_PLATFORM
  • TARGET_DISABLE_TRIPLE_BUFFERING
  • TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
  • NUM_FRAMEBUFFER_SURFACE_BUFFERS
  • TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK
  • VSYNC_EVENT_PHASE_OFFSET_NS
  • SF_VSYNC_EVENT_PHASE_OFFSET_NS
  • PRESENT_TIME_OFFSET_FROM_VSYNC_NS
  • MAX_VIRTUAL_DISPLAY_DIMENSION

ایجاد واسط HAL

پیکربندی‌های ساخت برای یک زیرسیستم ازطریق میانای HAL قابل‌دسترسی است، درحالی‌که میاناهای ارائه مقادیر پیکربندی در بسته HAL android.hardware.configstore (درحال‌حاضر در نسخه ۱.۰) گروه‌بندی می‌شوند. برای مثال، برای ایجاد فایل میانای HAL برای surfaceflinger، در hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal:

package android.hardware.configstore@1.0;

interface ISurfaceFlingerConfigs {
    // TO-BE-FILLED-BELOW
};

پس‌از ایجاد فایل .hal، hardware/interfaces/update-makefiles.sh را اجرا کنید تا فایل .hal جدید را به فایل‌های Android.bp و Android.mk اضافه کنید.

افزودن توابع برای پرچم‌های ساخت

برای هر پرچم ساخت، تابع جدیدی به میانای کاربری اضافه کنید. برای مثال، در hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal:

interface ISurfaceFlingerConfigs {
    disableTripleBuffering() generates(OptionalBool ret);
    forceHwcForVirtualDisplays() generates(OptionalBool ret);
    enum NumBuffers: uint8_t {
        USE_DEFAULT = 0,
        TWO = 2,
        THREE = 3,
    };
    numFramebufferSurfaceBuffers() generates(NumBuffers ret);
    runWithoutSyncFramework() generates(OptionalBool ret);
    vsyncEventPhaseOffsetNs generates (OptionalUInt64 ret);
    presentTimeOffsetFromSyncNs generates (OptionalUInt64 ret);
    maxVirtualDisplayDimension() generates(OptionalInt32 ret);
};

هنگام افزودن تابع:

  • نام‌ها را خلاصه کنید. از تبدیل نام‌های متغیر فایل ساخت به نام‌های تابع خودداری کنید و به‌یاد داشته باشید که پیشوندهای TARGET_ و BOARD_ دیگر لازم نیستند.
  • افزودن نظر. به توسعه‌دهندگان کمک می‌کند هدف عنصر پیکربندی، نحوه تغییر رفتار چارچوب، مقادیر معتبر، و سایر اطلاعات مرتبط را درک کنند.

انواع برگشتی تابع می‌تواند Optional[Bool|String|Int32|UInt32|Int64|UInt64] باشد. انواع در types.hal در همان دایرکتوری تعریف می‌شوند و مقادیر اولیه را با فیلدی که نشان می‌دهد مقدار توسط HAL مشخص شده است یا نه می‌پیچند؛ اگر مشخص نشده باشد، از مقدار پیش‌فرض استفاده می‌شود.

struct OptionalString {
    bool specified;
    string value;
};

درصورت لزوم، شمارشی را که بهترین نماینده نوع عنصر پیکربندی است تعریف کنید و از آن شمارش به‌عنوان نوع برگشتی استفاده کنید. در مثال بالا، NumBuffers enum برای محدود کردن تعداد مقادیر معتبر تعریف شده است. هنگام تعریف چنین نوع داده‌های سفارشی، یک فیلد یا مقدار شمارشی (برای مثال، USE_DEFAULT) اضافه کنید تا مشخص شود که آیا مقدار توسط HAL تعیین شده است یا نه.

الزامی نیست که یک پرچم ساخت به یک تابع در HIDL تبدیل شود. مالکان واحد می‌توانند پرچم‌های ساختار نزدیک را به‌صورت جایگزین در یک ساختار جمع کنند و تابعی داشته باشند که آن ساختار را برمی‌گرداند (انجام این کار می‌تواند تعداد فراخوانی‌های تابع را کاهش دهد).

برای مثال، گزینه‌ای برای تجمیع دو پرچم ساخت در یک ساختار واحد در hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal به‌صورت زیر است:

 interface ISurfaceFlingerConfigs {
    // other functions here
    struct SyncConfigs {
        OptionalInt64 vsyncEventPhaseoffsetNs;
        OptionalInt64 presentTimeoffsetFromSyncNs;
    };
    getSyncConfigs() generates (SyncConfigs ret);
    // other functions here
};

جایگزین‌های یک تابع HAL

به‌عنوان جایگزینی برای استفاده از یک تابع HAL برای همه پرچم‌های ساخت، میانای HAL توابع ساده‌ای مثل getBoolean(string key) و getInteger(string key) را نیز ارائه می‌دهد. جفت‌های واقعی key=value در فایل‌های جداگانه ذخیره می‌شوند و سرویس HAL مقادیر را با خواندن/تجزیه کردن آن فایل‌ها ارائه می‌دهد.

اگرچه تعریف این رویکرد آسان است، اما مزایای ارائه‌شده توسط HIDL (نسخه‌بندی اجباری، سهولت مستندسازی، کنترل دسترسی) را شامل نمی‌شود و بنابراین توصیه نمی‌شود.

میاناهای تکی و چندگانه

طراحی میانای HAL برای موارد پیکربندی دو انتخاب را ارائه می‌دهد:

  • یک رابط واحد که همه موارد پیکربندی را پوشش می‌دهد
  • چندین میانای کاربری که هرکدام مجموعه‌ای از موارد پیکربندی مرتبط را پوشش می‌دهد

یک میانای تکی آسان‌تر است اما با اضافه شدن موارد پیکربندی بیشتر به فایل تکی، می‌تواند غیرقابل‌نگهداری شود. علاوه‌براین، کنترل دسترسی جزئی نیست، بنابراین فرایندی که به رابط دسترسی دارد می‌تواند همه عناصر پیکربندی را بخواند (دسترسی به مجموعه جزئی از عناصر پیکربندی امکان‌پذیر نیست). یا اگر دسترسی اعطا نشود، عناصر پیکربندی نمی‌توانند خوانده شوند.

به‌دلیل این مشکلات، Android از چند میانای دارای یک میانای HAL برای گروهی از موارد پیکربندی مرتبط استفاده می‌کند. برای مثال، ISurfaceflingerConfigs برای موارد پیکربندی مربوط به surfaceflinger، و IBluetoothConfigs برای موارد پیکربندی مربوط به بلوتوث.