رابط HAL را ایجاد کنید

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

  • نسخه‌بندی‌شده (برای افزودن موارد پیکربندی جدید، فروشندگان/OEMها باید صریحاً HAL را گسترش دهند)
  • مستندسازی شده
  • کنترل دسترسی با استفاده از SELinux
  • بررسی سلامت اقلام پیکربندی از طریق مجموعه تست فروشنده (بررسی محدوده، بررسی وابستگی متقابل بین اقلام و غیره)
  • API های تولید شده خودکار در 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);
};

هنگام اضافه کردن یک تابع:

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

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

struct OptionalString {
    bool specified;
    string value;
};

در صورت لزوم، enum ای را تعریف کنید که به بهترین شکل نوع آیتم پیکربندی را نشان می‌دهد و از آن enum به عنوان نوع بازگشتی استفاده کنید. در مثال بالا، enum 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 برای موارد پیکربندی دو گزینه را ارائه می‌دهد:

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

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

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