ایجاد رابط 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 (در حال حاضر در نسخه 1.0) گروه‌بندی می‌شوند. به عنوان مثال، برای ایجاد یک فایل رابط 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 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 برای موارد پیکربندی مرتبط با بلوتوث.