HIDL पैकेज में बताए गए हर इंटरफ़ेस का अपना खुद का C++ क्लास होता है इसके पैकेज के नेमस्पेस के अंदर. क्लाइंट और सर्वर अलग-अलग तरीके:
- सर्वर इंटरफ़ेस को लागू करते हैं.
- इंटरफ़ेस पर क्लाइंट कॉल के तरीके.
इंटरफ़ेस को सर्वर ने नाम से रजिस्टर किया जा सकता है या इसके तौर पर पास किया जा सकता है पैरामीटर को HIDL-तय तरीकों के लिए इस्तेमाल किया जाएगा. उदाहरण के लिए, फ़्रेमवर्क कोड का इंटरफ़ेस होगा, जो HAL से एसिंक्रोनस मैसेज पाने और उस इंटरफ़ेस को पास करने के लिए उसे सीधे HAL में भेजना चाहते हैं.
सर्वर लागू करना
IFoo
इंटरफ़ेस लागू करने वाले सर्वर में
अपने-आप जनरेट हुई IFoo
हेडर फ़ाइल:
#include <android/hardware/samples/1.0/IFoo.h>
हेडर को इसकी शेयर की गई लाइब्रेरी से अपने आप एक्सपोर्ट किया जाता है
IFoo
इंटरफ़ेस, जिससे लिंक करना है. IFoo.hal
का उदाहरण:
// IFoo.hal interface IFoo { someMethod() generates (vec<uint32_t>); ... }
IFoo इंटरफ़ेस को सर्वर पर लागू करने के लिए, स्केलेटन का उदाहरण:
// From the IFoo.h header using android::hardware::samples::V1_0::IFoo; class FooImpl : public IFoo { Return<void> someMethod(foo my_foo, someMethod_cb _cb) { vec<uint32_t> return_data; // Compute return_data _cb(return_data); return Void(); } ... };
किसी क्लाइंट को सर्वर इंटरफ़ेस उपलब्ध कराने के लिए, आपको ये काम कर सकते हैं:
- लागू किए गए इंटरफ़ेस को रजिस्टर करें
hwservicemanager
(जानकारी नीचे देखें),
या
- इंटरफ़ेस लागू करने की प्रोसेस को इंटरफ़ेस विधि (डेटा की जानकारी के लिए, एसिंक्रोनस कॉलबैक).
इंटरफ़ेस लागू करने के लिए रजिस्टर करते समय,
hwservicemanager
प्रोसेस, रजिस्टर किए गए HIDL इंटरफ़ेस को ट्रैक करती है
को उसके नाम और वर्शन से संबद्ध कर सकते हैं. सर्वर कोई HIDL इंटरफ़ेस रजिस्टर कर सकते हैं
नाम से लागू करें और क्लाइंट नाम के आधार पर सेवा लागू करने का अनुरोध कर सकते हैं
और वर्शन शामिल करें. यह प्रोसेस HIDL इंटरफ़ेस में काम करती है
android.hidl.manager@1.0::IServiceManager
.
अपने-आप जनरेट हुई हर HIDL इंटरफ़ेस हेडर फ़ाइल (जैसे कि IFoo.h
)
एक registerAsService()
तरीका उपलब्ध है, जिसका इस्तेमाल
hwservicemanager
की मदद से इंटरफ़ेस लागू किया गया है. सिर्फ़
ज़रूरी तर्क, क्लाइंट के रूप में इंटरफ़ेस लागू करने के नाम का नाम है
इस नाम का इस्तेमाल, hwservicemanager
से इंटरफ़ेस वापस पाने के लिए करें
बाद में:
::android::sp<IFoo> myFoo = new FooImpl(); ::android::sp<IFoo> mySecondFoo = new FooAnotherImpl(); status_t status = myFoo->registerAsService(); status_t anotherStatus = mySecondFoo->registerAsService("another_foo");
hwservicemanager
इन चीज़ों के कॉम्बिनेशन का इस्तेमाल करता है
चालू करने के लिए, [package@version::interface, instance_name]
को यूनीक के तौर पर सेट करना
अलग-अलग इंटरफ़ेस (या एक ही इंटरफ़ेस के अलग-अलग वर्शन)
बिना किसी कॉन्फ़्लिक्ट के एक जैसे इंस्टेंस नाम के साथ. अगर आपको कॉल करना है
registerAsService()
पैकेज का वही वर्शन, इंटरफ़ेस,
और इंस्टेंस नाम, hwservicemanager
अपना संदर्भ
पहले से रजिस्टर की गई सेवा है और नई सेवा का इस्तेमाल करती है.
क्लाइंट लागू करने की प्रक्रिया
सर्वर की तरह ही, क्लाइंट को हर इंटरफ़ेस को #include
करना होगा
इससे यह पता चलता है:
#include <android/hardware/samples/1.0/IFoo.h>
क्लाइंट दो तरीकों से इंटरफ़ेस बना सकता है:
I<InterfaceName>::getService
के ज़रिए (hwservicemanager
)- इंटरफ़ेस तरीके से
अपने-आप जनरेट होने वाली हर इंटरफ़ेस की हेडर फ़ाइल में एक स्टैटिक getService
होता है
तरीका है जिसका इस्तेमाल
hwservicemanager
:
// getService returns nullptr if the service can't be found sp<IFoo> myFoo = IFoo::getService(); sp<IFoo> myAlternateFoo = IFoo::getService("another_foo");
अब क्लाइंट के पास IFoo
का इंटरफ़ेस है. इस पर वह कॉल करने का तरीका बता सकता है
इसे ऐसे मानो कि उसे कोई लोकल क्लास लागू किया गया हो. असल में, लागू करने का तरीका
उसी प्रक्रिया में, किसी अलग प्रक्रिया में या किसी अन्य डिवाइस पर भी चल सकता है
(HAL रिमोटिंग के साथ). क्योंकि क्लाइंट ने getService
को कॉल किया
पैकेज के 1.0
वर्शन से IFoo
ऑब्जेक्ट शामिल किया गया,
hwservicemanager
सर्वर को लागू करने का तरीका सिर्फ़ तब दिखाता है, जब
लागू करने की सुविधा 1.0
क्लाइंट के साथ काम करती है. व्यावहारिक तौर पर, यह
इसका मतलब सिर्फ़ 1.n
वर्शन (वर्शन) के साथ लागू सर्वर से है
x.(y+1)
इंटरफ़ेस का इस्तेमाल किया जाना चाहिए (इनसे इनहेरिट किया जाता है)
x.y
).
इसके अलावा, कास्ट करने के लिए castFrom
तरीका दिया गया है
अलग-अलग इंटरफ़ेस होने चाहिए. यह तरीका, रिमोट पर IPC कॉल करके काम करता है
इंटरफ़ेस का उपयोग करें, ताकि यह पक्का किया जा सके कि दिया गया प्रकार वही है जो
अनुरोध किया गया है. अगर अनुरोध किया गया टाइप उपलब्ध नहीं है, तो nullptr
वापस किया गया.
sp<V1_0::IFoo> foo1_0 = V1_0::IFoo::getService(); sp<V1_1::IFoo> foo1_1 = V1_1::IFoo::castFrom(foo1_0);
एसिंक्रोनस कॉलबैक
एचएएल को लागू करने के कई मौजूदा तरीके, एसिंक्रोनस हार्डवेयर के साथ इस्तेमाल किए जाते हैं. इसका मतलब है कि तो उन्हें नए इवेंट की सूचना देने के लिए एक एसिंक्रोनस तरीका चाहिए होता है हुआ. HIDL इंटरफ़ेस का इस्तेमाल एसिंक्रोनस कॉलबैक के तौर पर किया जा सकता है, क्योंकि HIDL इंटरफ़ेस फ़ंक्शन, HIDL इंटरफ़ेस ऑब्जेक्ट को पैरामीटर के रूप में ले सकते हैं.
इंटरफ़ेस फ़ाइल IFooCallback.hal
का उदाहरण:
package android.hardware.samples@1.0; interface IFooCallback { sendEvent(uint32_t event_id); sendData(vec<uint8_t> data); }
IFoo
में नए तरीके का उदाहरण, जो
IFooCallback
पैरामीटर:
package android.hardware.samples@1.0; interface IFoo { struct Foo { int64_t someValue; handle myHandle; }; someMethod(Foo foo) generates (int32_t ret); anotherMethod() generates (vec<uint32_t>); registerCallback(IFooCallback callback); };
IFoo
इंटरफ़ेस का इस्तेमाल करने वाला क्लाइंट
IFooCallback
इंटरफ़ेस का सर्वर; इससे पता चलता है कि
IFooCallback
को लागू करना:
class FooCallback : public IFooCallback { Return<void> sendEvent(uint32_t event_id) { // process the event from the HAL } Return<void> sendData(const hidl_vec<uint8_t>& data) { // process data from the HAL } };
यह उसे आसानी से
IFoo
इंटरफ़ेस:
sp<IFooCallback> myFooCallback = new FooCallback(); myFoo.registerCallback(myFooCallback);
IFoo
को लागू करने वाला सर्वर इसे
sp<IFooCallback>
ऑब्जेक्ट. यह कॉलबैक को स्टोर कर सकता है और
जब भी वह इस इंटरफ़ेस का उपयोग करना चाहे तो क्लाइंट में वापस जा सकता है.
मरने वाले
सेवा लागू करने की प्रोसेस अलग-अलग होती है, इसलिए ऐसा हो सकता है
कि क्लाइंट के जीवित रहने पर किसी इंटरफ़ेस को लागू करने की प्रक्रिया खत्म हो जाती है.
इंटरफ़ेस ऑब्जेक्ट पर मौजूद कोई भी ऐसी कॉल जो बंद हो चुकी प्रोसेस में होस्ट की गई है
ट्रांसपोर्ट की गड़बड़ी के साथ (isOK()
false
दिखाता है). इसका सिर्फ़ यही एक तरीका है
ऐसी असफलता से ठीक करने का अर्थ है कि सेवा के नए इंस्टेंस का अनुरोध
I<InterfaceName>::getService()
को कॉल किया जा रहा है. यह सुविधा सिर्फ़ तब काम करती है, जब
क्रैश होने की प्रक्रिया फिर से शुरू हो गई है और
servicemanager
(यह आम तौर पर एचएएल लागू करने पर लागू होता है).
इस समस्या से निपटने के बजाय, इंटरफ़ेस के क्लाइंट भी
किसी सेवा के खत्म होने की सूचना पाने के लिए, मृत्युएज़ रिसीपिएंट को रजिस्टर करें.
वापस लाए गए IFoo
इंटरफ़ेस पर ऐसी सूचनाओं के लिए रजिस्टर करने के लिए,
क्लाइंट ये काम कर सकता है:
foo->linkToDeath(recipient, 1481 /* cookie */);
recipient
पैरामीटर
HIDL का उपलब्ध कराया गया android::hardware::hidl_death_recipient
इंटरफ़ेस,
इसमें एक तरीका serviceDied()
होता है, जिसे
जब इंटरफ़ेस को होस्ट करने वाली प्रोसेस खत्म हो जाती है, तब RPC थ्रेडपूल में एक थ्रेड से लिया जाएगा:
class MyDeathRecipient : public android::hardware::hidl_death_recipient { virtual void serviceDied(uint64_t cookie, const android::wp<::android::hidl::base::V1_0::IBase>& who) { // Deal with the fact that the service died } }
cookie
पैरामीटर में वह कुकी शामिल है जिसे
linkToDeath()
, जबकि who
पैरामीटर में
क्लाइंट में सेवा को दर्शाने वाले ऑब्जेक्ट के लिए कमज़ोर पॉइंटर.
ऊपर दिया गया सैंपल कॉल, cookie
बराबर है 1481 और who
foo
के बराबर है.
मरने वाले व्यक्ति का रजिस्ट्रेशन रजिस्टर करने के बाद, उसका रजिस्ट्रेशन रद्द भी किया जा सकता है:
foo->unlinkToDeath(recipient);