Android 8 معماری سیستمعامل Android را بازسازی میکند تا میاناهای واضحی بین پلاتفرم Android مستقل از دستگاه و کد مختص دستگاه و فروشنده تعریف کند.
Android ازقبل بسیاری از این رابطها را در قالب رابطهای HAL تعریف میکند،
که بهعنوان سرایندهای C در hardware/libhardware تعریف شدهاند. HIDL این میاناهای HAL را با میاناهای پایدار و نسخهبندیشده جایگزین میکند که میتوانند میاناهای HIDL سمت کارخواه و سمت سرور در C++ (توضیحات در زیر) یا Java باشند.
صفحههای این بخش پیادهسازیهای C++ از میاناهای HIDL را شرح میدهند،
ازجمله جزئیات مربوط به فایلهای تولیدشده خودکار از فایلهای HIDL .hal
توسط کامپایلر hidl-gen، نحوه بستهبندی این فایلها، و
نحوه ادغام این فایلها با کد C++ که از آنها استفاده میکند.
پیادهسازیهای کارخواه و سرور
واسطهای HIDL پیادهسازیهای کارخواه و سرور دارند:
- کاربر میانای HIDL کدی است که با فراخوانی روشهای آن از میانای استفاده میکند.
- سرور پیادهسازی یک میانای HIDL است که تماسها را از مشتریان دریافت میکند و نتایج را (درصورت نیاز) برمیگرداند.
در انتقال از libhardware HAL به HIDL HAL، پیادهسازی HAL به سرور تبدیل میشود و فرایند فراخوانی به HAL به کلاینت تبدیل میشود. پیادهسازیهای پیشفرض میتوانند هم HALهای عبوری و هم HALهای متصلشده را ارائه دهند و ممکن است با گذشت زمان تغییر کنند:

شکل ۱. پیشرفت توسعه برای HALهای قدیمی.
ایجاد مشتری HAL
با گنجاندن کتابخانههای HAL در makefile شروع کنید:
- سازنده:
LOCAL_SHARED_LIBRARIES += android.hardware.nfc@1.0 - Soong:
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
برای 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 میشود. با نامگذاری باینری به این شکل، مشتریان نسخه ۲.۰ میتوانند آن را مستقیماً بازیابی کنند،
و مشتریان نسخه ۲.۱ میتوانند پیادهسازی را ارتقا دهند.
سپس، جای خالیها را با عملکرد پر کنید و یک دیمون راهاندازی کنید. نمونه کد کارگزار (پشتیبانی از انتقال):
#include <hidl/LegacySupport.h> int main(int /* argc */, char* /* argv */ []) { return defaultPassthroughServiceImplementation<INfc>("nfc"); }
defaultPassthroughServiceImplementation برای کتابخانه -impl ارائهشده تماس میگیرد
dlopen() و آن را بهعنوان
سرویس دستهبندیشده ارائه میدهد. کد دیمون نمونه (برای سرویس خالص بایندرشده):
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) قرار دارد، اما میتواند در هر جایی باشد.
sepolicy برای کلاس خاصی از HALها مشخصه hal_<module> (برای مثال،
hal_nfc) است. این مشخصه باید بر دیمونی که HAL خاصی را اجرا میکند اعمال شود (اگر فرایند یکسانی به چندین HAL سرویس میدهد، چندین مشخصه را میتوان بر آن اعمال کرد).