HIDL C ++

يقوم Android O بإعادة تصميم نظام التشغيل Android لتحديد واجهات واضحة بين نظام Android المستقل عن الجهاز والرمز الخاص بالجهاز والمورد. يعرّف Android بالفعل العديد من هذه الواجهات في شكل واجهات HAL ، والتي تُعرَّف برؤوس C في hardware/libhardware . يستبدل HIDL واجهات HAL هذه بواجهات مستقرة ذات إصدار ، والتي يمكن أن تكون واجهات HIDL من جانب العميل والخادم في C ++ (الموضحة أدناه) أو Java .

تصف الصفحات في هذا القسم تطبيقات C ++ لواجهات HIDL ، بما في ذلك تفاصيل حول الملفات التي تم إنشاؤها تلقائيًا من ملفات .hal بواسطة مترجم hidl-gen ، وكيفية تجميع هذه الملفات ، وكيفية دمج هذه الملفات مع كود C ++ الذي يستخدمهم.

تطبيقات العميل والخادم

تحتوي واجهات HIDL على تطبيقات للعميل والخادم:

  • عميل واجهة HIDL هو الرمز الذي يستخدم الواجهة عن طريق استدعاء الطرق عليها.
  • الخادم هو تنفيذ لواجهة HIDL التي تستقبل مكالمات من العملاء وترجع النتائج (إذا لزم الأمر).

أثناء الانتقال من HALs من libhardware إلى HIDL HAL ، يصبح تطبيق HAL هو الخادم وتصبح العملية التي تستدعي إلى HAL هي العميل. يمكن أن تخدم عمليات التنفيذ الافتراضية كلاً من HALs المرتبط والمرور ، ويمكن أن تتغير بمرور الوقت:

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

إنشاء عميل 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 لديك وأنشأت بالفعل ملفات makefiles لـ 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 هنا إصدار HAL الفعلي. من خلال تسمية البرنامج الثنائي مثل هذا ، يمكن للعملاء 2.0 استرداده مباشرة ، ويمكن للعملاء 2.1 تنشيط التنفيذ.

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

#include <hidl/LegacySupport.h>

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

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