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 में मेमोरी शेयर करने की प्रोसेस के बीच पास किया जाना चाहिए. यहां की यात्रा पर हूं
शेयर की गई मेमोरी का इस्तेमाल करें:
IAllocator
का एक इंस्टेंस पाएं (फ़िलहाल, सिर्फ़ इंस्टेंस) "अश्मेम" उपलब्ध है) और इसका इस्तेमाल शेयर की गई मेमोरी को असाइन करने के लिए करें.IAllocator::allocate()
,hidl_memory
दिखाता है ऑब्जेक्ट जिसे HIDL RPC के ज़रिए पास किया जा सकता है और जिसका इस्तेमाल करके प्रोसेस में मैप किया जा सकता हैlibhidlmemory
काmapMemory
फ़ंक्शन.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<>
की तरह काम करता है.