HIDL C++

اندروید 8 سیستم عامل اندروید را بازسازی می کند تا رابط های واضحی بین پلتفرم اندروید مستقل از دستگاه و کدهای دستگاه و فروشنده مشخص کند. اندروید در حال حاضر بسیاری از این رابط‌ها را در قالب رابط‌های HAL تعریف می‌کند که به عنوان هدر C در hardware/libhardware تعریف شده‌اند. HIDL این رابط‌های HAL را با اینترفیس‌های نسخه‌دار و پایدار جایگزین می‌کند، که می‌توانند رابط‌های HIDL سمت سرویس گیرنده و سمت سرور در C++ (شرح زیر) یا جاوا باشند.

صفحات این بخش، پیاده‌سازی C++ رابط‌های HIDL، شامل جزئیات مربوط به فایل‌های تولید شده خودکار از فایل‌های .hal توسط کامپایلر hidl-gen ، نحوه بسته‌بندی این فایل‌ها، و نحوه ادغام این فایل‌ها با کد C++ را توضیح می‌دهند. از آنها استفاده می کند.

پیاده سازی کلاینت و سرور

رابط های HIDL دارای پیاده سازی های مشتری و سرور هستند:

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

در انتقال از HAL های libhardware به HIDL HAL، اجرای HAL به سرور تبدیل می شود و فرآیند فراخوانی به HAL به مشتری تبدیل می شود. پیاده‌سازی‌های پیش‌فرض می‌توانند هم HAL‌های عبوری و هم بایندر شده را ارائه دهند و در طول زمان تغییر می‌کنند:

شکل 1. پیشرفت توسعه برای HAL های قدیمی.

کلاینت HAL را ایجاد کنید

با گنجاندن کتابخانه های HAL در makefile شروع کنید:

  • ساخت: LOCAL_SHARED_LIBRARIES += android.hardware.nfc@1.0
  • آهنگ: shared_libs: [ …, android.hardware.nfc@1.0 ]

در مرحله بعد، فایل های هدر HAL را اضافه کنید:

#include <android/hardware/nfc/1.0/IFoo.h>

// in code:
sp<IFoo> client = IFoo::getService();
client->doThing();

سرور HAL را ایجاد کنید

برای ایجاد پیاده‌سازی HAL، باید فایل‌های .hal را داشته باشید که نشان‌دهنده HAL شما هستند و قبلاً با استفاده از -Lmakefile یا -Landroidbp در hidl-gen فایل‌های make-files برای HAL شما ایجاد کرده‌اند ( ./hardware/interfaces/update-makefiles.sh این کار را برای فایل های HAL داخلی و مرجع خوبی است). هنگام انتقال بر روی HAL ها از libhardware ، می توانید بسیاری از این کارها را به راحتی با استفاده از c2hal انجام دهید.

برای ایجاد فایل های لازم برای پیاده سازی HAL خود:

PACKAGE=android.hardware.nfc@1.0
LOC=hardware/interfaces/nfc/1.0/default/
m -j hidl-gen
hidl-gen -o $LOC -Lc++-impl -randroid.hardware:hardware/interfaces \
    -randroid.hidl:system/libhidl/transport $PACKAGE
hidl-gen -o $LOC -Landroidbp-impl -randroid.hardware:hardware/interfaces \
    -randroid.hidl:system/libhidl/transport $PACKAGE

برای اینکه HAL در حالت عبور کار کند، باید تابع HIDL_FETCH_IModuleName در /(system|vendor|...)/lib(64)?/hw/android.hardware.package@3.0-impl( OPTIONAL_IDENTIFIER ).so داشته باشید. که در آن OPTIONAL_IDENTIFIER رشته ای است که اجرای گذر را شناسایی می کند. الزامات حالت عبور به طور خودکار توسط دستورات بالا برآورده می شود، که همچنین هدف android.hardware.nfc@1.0-impl را ایجاد می کند، اما می توان از هر برنامه افزودنی استفاده کرد. به عنوان مثال android.hardware.nfc@1.0-impl-foo از -foo برای متمایز کردن خود استفاده می کند.

اگر یک HAL یک نسخه کوچک یا پسوند HAL دیگری باشد، باید از HAL پایه برای نامگذاری این باینری استفاده شود. برای مثال، پیاده‌سازی‌های android.hardware.graphics.mapper@2.1 همچنان باید در یک باینری به نام android.hardware.graphics.mapper@2.0-impl( OPTIONAL_IDENTIFIER ) باشند. معمولاً، OPTIONAL_IDENTIFIER در اینجا شامل نسخه HAL واقعی می‌شود. با نامگذاری باینری به این صورت، مشتریان 2.0 می توانند مستقیماً آن را بازیابی کنند و کلاینت های 2.1 می توانند پیاده سازی را ارتقا دهند.

در مرحله بعد، موارد خرد را با قابلیت پر کنید و یک دیمون راه اندازی کنید. کد دیمون نمونه (پشتیبانی از عبور):

#include <hidl/LegacySupport.h>

int main(int /* argc */, char* /* argv */ []) {
    return defaultPassthroughServiceImplementation<INfc>("nfc");
}

defaultPassthroughServiceImplementation dlopen() برای کتابخانه -impl ارائه شده فراخوانی می کند و آن را به عنوان یک سرویس binderized ارائه می کند. کد دیمون نمونه (برای سرویس بایندر شده خالص):

int main(int /* argc */, char* /* argv */ []) {
    // This function must be called before you join to ensure the proper
    // number of threads are created. The threadpool never exceeds
    // size one because of this call.
    ::android::hardware::configureRpcThreadpool(1 /*threads*/, true /*willJoin*/);

    sp<INfc> nfc = new Nfc();
    const status_t status = nfc->registerAsService();
    if (status != ::android::OK) {
        return 1; // or handle error
    }

    // Adds this thread to the threadpool, resulting in one total
    // thread in the threadpool. We could also do other things, but
    // would have to specify 'false' to willJoin in configureRpcThreadpool.
    ::android::hardware::joinRpcThreadpool();
    return 1; // joinRpcThreadpool should never return
}

این دیمون معمولاً در $PACKAGE + "-service-suffix" (مثلاً android.hardware.nfc@1.0-service ) زندگی می کند، اما می تواند در هر جایی باشد. سیاست برای یک کلاس خاص از HAL ها، ویژگی hal_<module> است (به عنوان مثال، hal_nfc) . این ویژگی باید برای دیمونی که یک HAL خاص را اجرا می کند اعمال شود (اگر همان فرآیند چندین HAL را ارائه می دهد، چندین ویژگی می تواند برای آن اعمال شود).