HIDL C++

يُعيد 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 HALs إلى HIDL HALs، يجب أن تكون HAL يصبح التنفيذ هو الخادم وتصبح العملية التي تستدعي الدخول إلى HAL للعميل. يمكن أن تخدم آليات التنفيذ التلقائية كلاً من العبور والدمج HALs ويمكن أن تتغير بمرور الوقت:

الشكل 1. تقدم تطوير HALs القديمة.

إنشاء برنامج 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 (يجري ./hardware/interfaces/update-makefiles.sh ذلك للمستخدمين الداخليين HAL، وهو مرجع جيد). عند نقل HALs من 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 هنا مستوى تجريد الخلايا البيئي الفعلي. . عن طريق تسمية البرنامج الثنائي على هذا النحو، يمكن لعملاء الإصدار 2.0 استرداده مباشرة، والإصدار 2.1 من العملاء يمكنهم دعم التنفيذ.

بعد ذلك، يجب ملء بيانات التنويع بالوظائف وإعداد برنامج خفي. مثال رمز خفي (دعم العبور):

#include <hidl/LegacySupport.h>

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

مكالمتان (defaultPassthroughServiceImplementation) dlopen() لمكتبة -impl المقدَّمة وتقديمها على أنّها خدمة مكتبية. مثال على رمز خفيف (للخدمة التي تجمع بين البيانات بشكل كامل):

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 على وفئة HALs هي التصنيف hal_<module> (على سبيل المثال، hal_nfc) يجب تطبيق هذه السمة على البرنامج الخفي الذي يشغِّل طبقة تجريد الأجهزة (HAL) معينة (إذا كانت العملية نفسها تخدم العديد من HALs، فإن سمات تطبيق النموذج الجديد عليها).