इंटरफ़ेस

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();
    }
    ...
};

किसी क्लाइंट को सर्वर इंटरफ़ेस उपलब्ध कराने के लिए, आपको ये काम कर सकते हैं:

  1. लागू किए गए इंटरफ़ेस को रजिस्टर करें hwservicemanager (जानकारी नीचे देखें),

    या

  2. इंटरफ़ेस लागू करने की प्रोसेस को इंटरफ़ेस विधि (डेटा की जानकारी के लिए, एसिंक्रोनस कॉलबैक).

इंटरफ़ेस लागू करने के लिए रजिस्टर करते समय, 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);