Android 8 में Android OS को फिर से डिज़ाइन किया गया है, ताकि डिवाइस पर काम करने वाले Android प्लैटफ़ॉर्म और डिवाइस और वेंडर के हिसाब से कोड के बीच साफ़ इंटरफ़ेस तय किए जा सकें.
Android पहले से ही एचएएल इंटरफ़ेस के तौर पर ऐसे कई इंटरफ़ेस तय करता है, जिन्हें hardware/libhardware
में C हेडर के तौर पर तय किया गया है. HIDL, इन HAL इंटरफ़ेस को स्थिर और वर्शन वाले इंटरफ़ेस से बदल देता है. ये इंटरफ़ेस, C++ (यहां बताया गया है) या Java में क्लाइंट- और सर्वर-साइड HIDL इंटरफ़ेस हो सकते हैं.
इस सेक्शन के पेजों पर, HIDL इंटरफ़ेस के C++ लागू करने के बारे में बताया गया है. इसमें, hidl-gen
कंपाइलर की मदद से HIDL .hal
फ़ाइलों से अपने-आप जनरेट होने वाली फ़ाइलों के बारे में जानकारी शामिल है. साथ ही, इन फ़ाइलों को पैकेज करने के तरीके और इन फ़ाइलों को इस्तेमाल करने वाले C++ कोड के साथ इंटिग्रेट करने के तरीके के बारे में भी बताया गया है.
क्लाइंट और सर्वर पर लागू करना
HIDL इंटरफ़ेस में क्लाइंट और सर्वर, दोनों को लागू किया जाता है:
- HIDL इंटरफ़ेस का क्लाइंट वह कोड होता है जो इंटरफ़ेस के तरीकों को कॉल करके, इंटरफ़ेस का इस्तेमाल करता है.
- सर्वर, HIDL इंटरफ़ेस का एक ऐसा वर्शन है जो क्लाइंट से कॉल पाता है और ज़रूरत पड़ने पर नतीजे दिखाता है.
libhardware
एचएएल से HIDL एचएएल पर स्विच करने पर, एचएएल लागू करने की प्रोसेस, सर्वर बन जाती है और एचएएल को कॉल करने वाली प्रोसेस, क्लाइंट बन जाती है. डिफ़ॉल्ट तौर पर लागू किए गए एचएएल, पासथ्रू और बाइंडर वाले एचएएल, दोनों के तौर पर काम कर सकते हैं. साथ ही, समय के साथ इनमें बदलाव भी हो सकता है:
पहली इमेज. लेगसी एचएएल के लिए डेवलपमेंट की प्रोग्रेस.
HAL क्लाइंट बनाना
मेकफ़ाइल में HAL लाइब्रेरी शामिल करके शुरुआत करें:
- बनाएं:
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
फ़ाइलें होनी चाहिए जो आपके एचएएल को दिखाती हों. साथ ही, आपने hidl-gen
पर -Lmakefile
या -Landroidbp
का इस्तेमाल करके, अपने एचएएल के लिए पहले से ही मेकफ़ाइलें जनरेट कर ली हों (./hardware/interfaces/update-makefiles.sh
, एचएएल की इंटरनल फ़ाइलों के लिए ऐसा करता है और यह एक अच्छा रेफ़रंस है). libhardware
से एचएएल ट्रांसफ़र करते समय, c2hal का इस्तेमाल करके बहुत सारा काम आसानी से किया जा सकता है.
एचएएल लागू करने के लिए ज़रूरी फ़ाइलें बनाने के लिए:
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
एचएएल के पासथ्रू मोड में काम करने के लिए, आपके पास 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
का इस्तेमाल करता है.
अगर कोई एचएएल किसी दूसरे एचएएल का छोटा वर्शन या एक्सटेंशन है, तो इस बाइनरी को नाम देने के लिए, बेस एचएएल का इस्तेमाल किया जाना चाहिए. उदाहरण के लिए,
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
, दी गई -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_<module>
है. उदाहरण के लिए, hal_nfc)
. यह एट्रिब्यूट, किसी खास एचएएल को चलाने वाले डेमन पर लागू किया जाना चाहिए. अगर एक ही प्रोसेस कई एचएएल को दिखाती है, तो उस पर कई एट्रिब्यूट लागू किए जा सकते हैं.