डेटा प्रकार

HIDL डेटा का एलान, C++ स्टैंडर्ड-लेआउट डेटा स्ट्रक्चर जनरेट करता है. ये ऐसी किसी भी जगह पर रखा जा सकता है जो स्वाभाविक लगती है (स्टैक पर, फ़ाइल पर या भी जनरेट किया जा सकता है और इसे एक ही तरीके से बनाया जा सकता है. क्लाइंट कोड कॉन्सट रेफ़रंस और प्रिमिटिव टाइप में पास होने वाले HIDL प्रॉक्सी कोड को कॉल करता है, जबकि स्टब और प्रॉक्सी कोड सीरियलाइज़ेशन के विवरण छिपा देते हैं.

ध्यान दें: कभी भी डेवलपर का लिखा हुआ कोड नहीं होता डेटा स्ट्रक्चर को क्रम में लगाने या डीसीरियलाइज़ करने के लिए ज़रूरी है.

नीचे दी गई टेबल में, HIDL प्रिमिटिव से C++ डेटा टाइप को मैप किया गया है:

HIDL टाइप C++ टाइप हेडर/लाइब्रेरी
enum enum class
uint8_t..uint64_t uint8_t..uint64_t <stdint.h>
int8_t..int64_t int8_t..int64_t <stdint.h>
float float
double double
vec<T> hidl_vec<T> libhidlbase
T[S1][S2]...[SN] T[S1][S2]...[SN]
string hidl_string libhidlbase
handle hidl_handle libhidlbase
safe_union (custom) struct
struct struct
union union
fmq_sync MQDescriptorSync libhidlbase
fmq_unsync MQDescriptorUnsync libhidlbase

यहां दिए गए सेक्शन में, अलग-अलग तरह के डेटा के बारे में ज़्यादा जानकारी दी गई है.

Enum

HIDL में एक enum C++ में एक enum बन जाता है. जैसे:

enum Mode : uint8_t { WRITE = 1 << 0, READ = 1 << 1 };
enum SpecialMode : Mode { NONE = 0, COMPARE = 1 << 2 };

... बन जाता है:

enum class Mode : uint8_t { WRITE = 1, READ = 2 };
enum class SpecialMode : uint8_t { WRITE = 1, READ = 2, NONE = 0, COMPARE = 4 };

Android 10 और उसके बाद के वर्शन में, ईनम को दोहराया जा सकता है ज़्यादा से ज़्यादा ::android::hardware::hidl_enum_range का इस्तेमाल किया जा रहा है. इस रेंज में इसमें हर एन्यूमरेटर उसी क्रम में शामिल होता है जिस क्रम में यह HIDL सोर्स कोड में दिखता है इसमें माता-पिता की सूची से लेकर आख़िरी बच्चे तक का डेटा शामिल किया गया है. उदाहरण के लिए, यह कोड फिर से लागू होता है WRITE, READ, NONE, और COMPARE इस क्रम में. ऊपर SpecialMode दिए गए हैं:

template <typename T>
using hidl_enum_range = ::android::hardware::hidl_enum_range<T>

for (SpecialMode mode : hidl_enum_range<SpecialMode>) {...}

hidl_enum_range रिवर्स इटरेटर को भी लागू करता है और का इस्तेमाल constexpr संदर्भ में किया गया. अगर कोई वैल्यू, गिनती में दिखती है का इस्तेमाल करने पर, वह वैल्यू इस रेंज में कई बार दिखती है.

बिटफ़ील्ड<T>

bitfield<T> (जहां T, उपयोगकर्ता का तय किया गया ईनम है) C++ में उस ईनम का बुनियादी टाइप बन जाता है. ऊपर दिए गए उदाहरण में, bitfield<Mode>, uint8_t हो जाता है.

वीसी<T>

hidl_vec<T> क्लास टेंप्लेट इसका हिस्सा है libhidlbase का इस्तेमाल किया जा सकता है. इसकी मदद से, किसी भी HIDL टाइप के वेक्टर को पास किया जा सकता है का इस्तेमाल करें. तुलना किए जा सकने वाले तय साइज़ वाले कंटेनर hidl_array. hidl_vec<T> इसका इस्तेमाल करके, T टाइप के बाहरी डेटा बफ़र को पॉइंट करने के लिए शुरू किया गया है hidl_vec::setToExternal() फ़ंक्शन को कॉपी किया जा सकता है.

जनरेट किए गए कॉन्टेंट में निर्देश सही तरीके से लगाने/इस्तेमाल करने के अलावा C++ हेडर, vec<T> का इस्तेमाल करने से थोड़ी आसानी होती है std::vector और बेयर T में/से अनुवाद करने के लिए फ़ंक्शन पॉइंटर. अगर vec<T> का इस्तेमाल पैरामीटर के रूप में किया जाता है, तो फ़ंक्शन इसे इस्तेमाल करने से, एक तय सीमा से ज़्यादा समस्याएं आती हैं (दो प्रोटोटाइप जनरेट होते हैं) उसके लिए HIDL स्ट्रक्चर और std::vector<T> टाइप, दोनों को पास करें पैरामीटर.

कलेक्शन

hidl में कॉन्सटेंट अरे को hidl_array क्लास से दिखाया जाता है libhidlbase में. hidl_array<T, S1, S2, …, SN>, N डाइमेंशन वाले तय साइज़ का अरे दिखाता है T[S1][S2]…[SN].

स्ट्रिंग

hidl_string क्लास (libhidlbase का हिस्सा) इसका इस्तेमाल HIDL इंटरफ़ेस पर स्ट्रिंग पास करने के लिए किया जाता है और इसे /system/libhidl/base/include/hidl/HidlSupport.h. पहला स्टोरेज लोकेशन, क्लास में अपने कैरेक्टर बफ़र का पॉइंटर है.

hidl_string को पता है कि कैसे कन्वर्ट किया जा सकता है और किस तरह से std::string and char* (C-स्टाइल स्ट्रिंग) इसका इस्तेमाल कर रही हैं operator=, इंप्लिसिट कास्ट, और .c_str() फ़ंक्शन. HIDL स्ट्रिंग स्ट्रक्ट में सही कॉपी कंस्ट्रक्टर और असाइनमेंट हैं ऑपरेटर को जोड़ें:

  • किसी std::string या C स्ट्रिंग से HIDL स्ट्रिंग लोड करें.
  • HIDL स्ट्रिंग से नया std::string बनाएं.

इसके अलावा, HIDL स्ट्रिंग में कन्वर्ज़न कंस्ट्रक्टर होते हैं, इसलिए C स्ट्रिंग (char *) और C++ स्ट्रिंग (std::string) का इस्तेमाल इन पर किया जा सकता है HIDL स्ट्रिंग लेने वाले तरीके.

संरचना

HIDL के struct में सिर्फ़ तय साइज़ वाला डेटा टाइप हो सकता है और नहीं फ़ंक्शन. HIDL स्ट्रक्चर डेफ़िनिशन, सीधे स्टैंडर्ड-लेआउट पर मैप करती हैं C++ में struct है. यह पक्का करने के लिए कि struct के पास एक जैसा मेमोरी लेआउट. एक निर्देश में HIDL टाइप शामिल हो सकते हैं, जिनमें शामिल हैं वह handle, string, और vec<T> अलग-अलग वैरिएबल-अवधि वाले बफ़र पर ले जाते हैं.

हैंडल

चेतावनी: किसी भी तरह के पते से जुड़ी जानकारी (यहां तक कि ऑफ़िस या ऑफ़िस के पते पर भी) डिवाइस पते) कभी भी नेटिव हैंडल का हिस्सा नहीं होने चाहिए. इसे पास करना एक प्रोसेस के बीच की जानकारी खतरनाक होती है और उस पर हमला होने की आशंका होती है. अलग-अलग प्रोसेस के बीच पास होने वाली वैल्यू की पुष्टि करने के बाद ही, वे तय मेमोरी का इस्तेमाल करता है. गलत हैंडल की वजह से, मेमोरी ऐक्सेस या मेमोरी खराब हो जाना.

handle टाइप को hidl_handle से दिखाया जाता है C++ में स्ट्रक्चर है, जो const native_handle_t ऑब्जेक्ट (यह इस तारीख से Android में मौजूद है लंबे समय से जुड़ी हैं).

typedef struct native_handle
{
    int version;        /* sizeof(native_handle_t) */
    int numFds;         /* number of file descriptors at &data[0] */
    int numInts;        /* number of ints at &data[numFds] */
    int data[0];        /* numFds + numInts ints */
} native_handle_t;

डिफ़ॉल्ट रूप से, hidl_handle मालिकाना हक नहीं लेता है native_handle_t पॉइंटर का, यह रैप हो जाता है. यह सिर्फ़ इंटरनेट पर मौजूद पॉइंटर को native_handle_t में इस तरह सेव करें कि उसका इस्तेमाल किया जा सके दोनों 32- और 64-बिट प्रोसेस पर काम करते हैं.

ऐसे मामले जिनमें hidl_handle अपनी बंद की गई फ़ाइल का मालिक होता है डिस्क्रिप्टर में ये शामिल हैं:

  • setTo(native_handle_t* handle, bool shouldOwn) तरीके को कॉल करने के बाद, shouldOwn पैरामीटर इस पर सेट किया गया है true
  • जब कॉपी बनाकर hidl_handle ऑब्जेक्ट बनाया जाता है किसी दूसरे hidl_handle ऑब्जेक्ट से
  • जब hidl_handle ऑब्जेक्ट को किसी दूसरे ऑब्जेक्ट से कॉपी किया जाता है hidl_handle ऑब्जेक्ट

hidl_handle से इंप्लिसिट और एक्सप्लिसिट कन्वर्ज़न, दोनों मिलते हैं native_handle_t* ऑब्जेक्ट को और उससे जाने के लिए. मुख्य इस्तेमाल HIDL में handle टाइप, फ़ाइल डिस्क्रिप्टर को HIDL पर पास करने के लिए है इंटरफ़ेस. इसलिए, सिंगल फ़ाइल डिस्क्रिप्टर को native_handle_t, जिसमें कोई int नहीं है और एक सिंगल भी नहीं है fd. अगर क्लाइंट और सर्वर अलग-अलग प्रोसेस में रहते हैं, तो RPC लागू करने से फ़ाइल डिस्क्रिप्टर का काम अपने आप हो जाता है, दोनों प्रोसेस एक ही फ़ाइल पर काम कर सकती हैं.

हालांकि, किसी फ़ाइल डिस्क्रिप्टर को hidl_handle में उस प्रक्रिया में मान्य है, यह फ़ंक्शन (फ़ंक्शन के वापस आने पर यह बंद हो जाता है). एक ऐसी प्रोसेस जो फ़ाइल डिस्क्रिप्टर का लगातार ऐक्सेस बनाए रखना ज़रूरी हैdup() बंद फ़ाइल डिस्क्रिप्टर चुनें या पूरे hidl_handle ऑब्जेक्ट को कॉपी करें.

यादें

HIDL memory टाइप, hidl_memory क्लास को मैप करता है libhidlbase में, जो शेयर की गई ऐसी मेमोरी दिखाती है जिसे मैप नहीं किया गया है. यह है वह ऑब्जेक्ट जिसे HIDL में मेमोरी शेयर करने की प्रोसेस के बीच पास किया जाना चाहिए. यहां की यात्रा पर हूं शेयर की गई मेमोरी का इस्तेमाल करें:

  1. IAllocator का एक इंस्टेंस पाएं (फ़िलहाल, सिर्फ़ इंस्टेंस) "अश्मेम" उपलब्ध है) और इसका इस्तेमाल शेयर की गई मेमोरी को असाइन करने के लिए करें.
  2. IAllocator::allocate(), hidl_memory दिखाता है ऑब्जेक्ट जिसे HIDL RPC के ज़रिए पास किया जा सकता है और जिसका इस्तेमाल करके प्रोसेस में मैप किया जा सकता है libhidlmemory का mapMemory फ़ंक्शन.
  3. mapMemory किसी sp<IMemory> ऑब्जेक्ट, जिसका इस्तेमाल मेमोरी को ऐक्सेस करने के लिए किया जा सकता है. (IMemory और IAllocator की परिभाषा यहां दी गई है android.hidl.memory@1.0.)

मेमोरी को असाइन करने के लिए, IAllocator के इंस्टेंस का इस्तेमाल किया जा सकता है:

#include <android/hidl/allocator/1.0/IAllocator.h>
#include <android/hidl/memory/1.0/IMemory.h>
#include <hidlmemory/mapping.h>
using ::android::hidl::allocator::V1_0::IAllocator;
using ::android::hidl::memory::V1_0::IMemory;
using ::android::hardware::hidl_memory;
....
  sp<IAllocator> ashmemAllocator = IAllocator::getService("ashmem");
  ashmemAllocator->allocate(2048, [&](bool success, const hidl_memory& mem) {
        if (!success) { /* error */ }
        // now you can use the hidl_memory object 'mem' or pass it around
  }));

मेमोरी में असल बदलाव IMemory से किए जाने चाहिए ऑब्जेक्ट, mem बनाने वाले हिस्से पर या उस तरफ़ HIDL RPC पर जाता है.

// Same includes as above

sp<IMemory> memory = mapMemory(mem);
void* data = memory->getPointer();
memory->update();
// update memory however you wish after calling update and before calling commit
data[0] = 42;
memory->commit();
// …
memory->update(); // the same memory can be updated multiple times
// …
memory->commit();

इंटरफ़ेस

इंटरफ़ेस को ऑब्जेक्ट के तौर पर पास किया जा सकता है. इंटरफ़ेस शब्द का इस्तेमाल किया जा सकता है android.hidl.base@1.0::IBase टाइप के लिए वाक्यात्मक शक्कर के रूप में; इसके अलावा, मौजूदा इंटरफ़ेस और इंपोर्ट किए गए इंटरफ़ेस एक टाइप के तौर पर.

इंटरफ़ेस को होल्ड करने वाले वैरिएबल, स्ट्रॉन्ग पॉइंटर होने चाहिए: sp<IName>. इंटरफ़ेस पैरामीटर लेने वाले HIDL फ़ंक्शन रॉ पॉइंटर को स्ट्रॉन्ग पॉइंटर में बदल देता है, जिससे ग़ैर-ज़रूरी व्यवहार होता है (पॉइंटर को अचानक हटाया जा सकता है). समस्याओं से बचने के लिए, HIDL को हमेशा स्टोर करें sp<> की तरह काम करता है.