डेटा टाइप

इस सेक्शन में, HIDL डेटा टाइप के बारे में बताया गया है. लागू करने से जुड़ी जानकारी के लिए, HIDL C++ (C++ लागू करने के लिए) या HIDL Java (Java लागू करने के लिए) देखें.

C++ से मिलती-जुलती बातें:

  • structs C++ सिंटैक्स का इस्तेमाल करता है; unions डिफ़ॉल्ट रूप से C++ सिंटैक्स का इस्तेमाल करता है. दोनों का नाम होना चाहिए. बिना नाम वाले स्ट्रक्चर और यूनियन काम नहीं करते.
  • HIDL में, C++ की तरह ही टाइपडेफ़ की अनुमति है.
  • C++ स्टाइल की टिप्पणियों की अनुमति है और उन्हें जनरेट की गई हेडर फ़ाइल में कॉपी किया जाता है.

Java से मिलती-जुलती चीज़ों में ये शामिल हैं:

  • हर फ़ाइल के लिए, HIDL एक Java-style नेमस्पेस तय करता है, जो android.hardware. से शुरू होना चाहिए. जनरेट किया गया C++ नेमस्पेस, ::android::hardware::… है.
  • फ़ाइल की सभी परिभाषाएं, Java-style interface रैपर में होती हैं.
  • HIDL ऐरे के एलान, C++ स्टाइल के बजाय Java स्टाइल के हिसाब से होते हैं. उदाहरण:
    struct Point {
        int32_t x;
        int32_t y;
    };
    Point[3] triangle;   // sized array
  • टिप्पणियां, javadoc फ़ॉर्मैट से मिलती-जुलती होती हैं.

डेटा दिखाने का तरीका

स्टैंडर्ड-लेआउट (सामान्य डेटा टाइप की ज़रूरी शर्तों का सबसेट) से बना struct या union, जनरेट किए गए C++ कोड में एक जैसा मेमोरी लेआउट होता है. इसे struct और union के सदस्यों पर साफ़ तौर पर अलाइनमेंट एट्रिब्यूट के साथ लागू किया जाता है.

प्राइमिटिव HIDL टाइप के साथ-साथ enum और bitfield टाइप (जो हमेशा प्राइमिटिव टाइप से मिलते-जुलते होते हैं), स्टैंडर्ड C++ टाइप पर मैप होते हैं. जैसे, cstdint से std::uint32_t.

Java में बिना हस्ताक्षर वाले टाइप काम नहीं करते. इसलिए, बिना हस्ताक्षर वाले HIDL टाइप, हस्ताक्षर वाले उस Java टाइप से मैप किए जाते हैं जो उनसे मिलता-जुलता हो. स्ट्रक्चर, Java क्लास में मैप होते हैं; कलेक्शन, Java कलेक्शन में मैप होते हैं; फ़िलहाल, यूनियन का इस्तेमाल Java में नहीं किया जा सकता. स्ट्रिंग को अंदरूनी तौर पर UTF8 के तौर पर सेव किया जाता है. Java सिर्फ़ UTF16 स्ट्रिंग के साथ काम करता है. इसलिए, Java के ज़रिए भेजी या उससे मिली स्ट्रिंग वैल्यू का अनुवाद किया जाता है. ऐसा हो सकता है कि दोबारा अनुवाद करने पर, वैल्यू एक जैसी न हों, क्योंकि कैरेक्टर सेट हमेशा आसानी से मैप नहीं होते.

C++ में IPC के ज़रिए मिलने वाले डेटा को const के तौर पर मार्क किया जाता है. यह डेटा, सिर्फ़ फ़ंक्शन कॉल के दौरान दिखता है. यह डेटा, रीड-ओनली मेमोरी में सेव होता है. Java में IPC के ज़रिए मिलने वाले डेटा को पहले से ही Java ऑब्जेक्ट में कॉपी कर लिया जाता है. इसलिए, इसे बिना किसी और कॉपी किए सेव किया जा सकता है और उसमें बदलाव किया जा सकता है.

एनोटेशन

टाइप के एलान में, Java-style एनोटेशन जोड़े जा सकते हैं. एनोटेशन को, एचआईडीएल कंपाइलर के वेंडर टेस्ट सुइट (वीटीएस) बैकएंड से पार्स किया जाता है. हालांकि, एनोटेशन को पार्स करने के बाद, एचआईडीएल कंपाइलर उन्हें समझ नहीं पाता. इसके बजाय, पार्स किए गए VTS एनोटेशन को VTS कंपाइलर (VTSC) मैनेज करता है.

एनोटेशन में Java सिंटैक्स का इस्तेमाल किया जाता है: @annotation या @annotation(value) या @annotation(id=value, id=value…) जहां वैल्यू, {} में एक कॉन्स्टेंट एक्सप्रेशन, स्ट्रिंग या वैल्यू की सूची हो सकती है, ठीक वैसे ही जैसे Java में होती है. एक ही नाम के कई एनोटेशन, एक ही आइटम से जुड़े हो सकते हैं.

एलान फ़ॉरवर्ड करना

हो सकता है कि HIDL में, स्ट्रक्चर को पहले से एलान न किया गया हो. इससे, उपयोगकर्ता के तय किए गए, खुद के रेफ़रंस वाले डेटा टाइप का इस्तेमाल नहीं किया जा सकता. उदाहरण के लिए, HIDL में लिंक की गई सूची या ट्री के बारे में नहीं बताया जा सकता. ज़्यादातर मौजूदा (Android 8.x से पहले के) एचएएल में, फ़ॉरवर्ड डिक्लेरेशन का सीमित इस्तेमाल किया जाता है. इन्हें हटाने के लिए, डेटा स्ट्रक्चर के डिक्लेरेशन को फिर से व्यवस्थित करें.

इस पाबंदी की मदद से, डेटा स्ट्रक्चर को वैल्यू के हिसाब से कॉपी किया जा सकता है. इसके लिए, पॉइंटर वैल्यू का ट्रैक रखने की ज़रूरत नहीं होती. ये वैल्यू, अपने-आप रेफ़र करने वाले डेटा स्ट्रक्चर में कई बार दिख सकती हैं. अगर एक ही डेटा को दो बार पास किया जाता है, जैसे कि एक ही डेटा पर ले जाने वाले दो मेथड पैरामीटर या vec<T>s के साथ, तो दो अलग-अलग कॉपी बनाई और डिलीवर की जाती हैं.

नेस्ट किए गए एलान

HIDL, नेस्ट किए गए एलान को जितने चाहें उतने लेवल तक इस्तेमाल करने की सुविधा देता है. हालांकि, एक अपवाद है, जिसे यहां बताया गया है. उदाहरण के लिए:

interface IFoo {
    uint32_t[3][4][5][6] multidimArray;

    vec<vec<vec<int8_t>>> multidimVector;

    vec<bool[4]> arrayVec;

    struct foo {
        struct bar {
            uint32_t val;
        };
        bar b;
    }
    struct baz {
        foo f;
        foo.bar fb; // HIDL uses dots to access nested type names
    }
    

हालांकि, इंटरफ़ेस टाइप सिर्फ़ vec<T> में एम्बेड किए जा सकते हैं और सिर्फ़ एक लेवल तक (vec<vec<IFoo>> नहीं).

रॉ पॉइंटर सिंटैक्स

HIDL भाषा में * का इस्तेमाल नहीं किया जाता. साथ ही, यह C/C++ रॉ पॉइंटर की सभी सुविधाओं के साथ काम नहीं करती. HIDL, पॉइंटर और ऐरे/वेक्टर को कैसे शामिल करता है, इस बारे में जानने के लिए vec<T> टेंप्लेट देखें.

इंटरफ़ेस

interface कीवर्ड का इस्तेमाल दो तरीकों से किया जा सकता है.

  • यह .hal फ़ाइल में इंटरफ़ेस की परिभाषा खोलता है.
  • इसका इस्तेमाल स्ट्रक्चर/यूनियन फ़ील्ड, मेथड पैरामीटर, और रिटर्न में खास टाइप के तौर पर किया जा सकता है. इसे सामान्य इंटरफ़ेस और android.hidl.base@1.0::IBase के लिए एक ही शब्द के तौर पर देखा जाता है.

उदाहरण के लिए, IServiceManager में यह तरीका है:

get(string fqName, string name) generates (interface service);

इस तरीके से, नाम के हिसाब से किसी इंटरफ़ेस को खोजा जा सकता है. यह इंटरफ़ेस को android.hidl.base@1.0::IBase से बदलने के लिए भी वैसा ही है.

इंटरफ़ेस को सिर्फ़ दो तरीकों से पास किया जा सकता है: टॉप-लेवल पैरामीटर के तौर पर या vec<IMyInterface> के सदस्य के तौर पर. ये नेस्ट किए गए वैक्टर, स्ट्रक्चर, ऐरे या यूनियन के सदस्य नहीं हो सकते.

MQDescriptorSync और MQDescriptorUnsync

MQDescriptorSync और MQDescriptorUnsync टाइप, सिंक किए गए या सिंक नहीं किए गए फ़ास्ट मैसेज क्यू (एफ़एमक्यू) डिस्क्रिप्टर को, HIDL इंटरफ़ेस पर पास करते हैं. ज़्यादा जानकारी के लिए, HIDL C++ देखें. Java में एफएमक्यू काम नहीं करते.

मेमोरी टाइप

memory टाइप का इस्तेमाल, HIDL में शेयर की गई मेमोरी को दिखाने के लिए किया जाता है. यह सिर्फ़ C++ में काम करता है. इस तरह की वैल्यू का इस्तेमाल, IMemory ऑब्जेक्ट को शुरू करने, मेमोरी को मैप करने, और उसे इस्तेमाल करने लायक बनाने के लिए, पाने वाले एंड पर किया जा सकता है. ज़्यादा जानकारी के लिए, HIDL C++ देखें.

चेतावनी: शेयर की गई स्मृति में डाला गया स्ट्रक्चर्ड डेटा, ऐसा होना चाहिए जिसका फ़ॉर्मैट memory को पास करने वाले इंटरफ़ेस वर्शन के लाइफ़टाइम के दौरान कभी न बदले. ऐसा न करने पर, एचएएल के साथ काम करने में गंभीर समस्याएं आ सकती हैं.

पॉइंटर का टाइप

pointer टाइप, सिर्फ़ HIDL के अंदरूनी इस्तेमाल के लिए है.

bitfield<T> टाइप टेंप्लेट

bitfield<T> में T एक उपयोगकर्ता की ओर से तय की गई वैल्यू है. इससे पता चलता है कि वैल्यू, T में तय की गई वैल्यू के बिटवाइज़-OR है. जनरेट किए गए कोड में, bitfield<T>, T के बुनियादी टाइप के तौर पर दिखता है. उदाहरण के लिए:

enum Flag : uint8_t {
    HAS_FOO = 1 << 0,
    HAS_BAR = 1 << 1,
    HAS_BAZ = 1 << 2
};
typedef bitfield<Flag> Flags;
setFlags(Flags flags) generates (bool success);

कंपाइलर, टाइप फ़्लैग को uint8_t की तरह ही हैंडल करता है.

(u)int8_t/(u)int16_t/(u)int32_t/(u)int64_t का इस्तेमाल क्यों नहीं किया जा सकता? bitfield का इस्तेमाल करने से, पाठक को HAL के बारे में ज़्यादा जानकारी मिलती है.अब उसे पता है कि setFlags, फ़्लैग की बिटवाइज़-OR वैल्यू लेता है. इसका मतलब है कि उसे पता है कि 16 के साथ setFlags को कॉल करना अमान्य है. bitfield के बिना, यह जानकारी सिर्फ़ दस्तावेज़ के ज़रिए दी जाती है. इसके अलावा, VTS यह भी देख सकता है कि फ़्लैग की वैल्यू, फ़्लैग की बिटवाइज़-OR है या नहीं.

प्राइमिटिव टाइप हैंडल

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

HIDL सेमेंटेक्स, वैल्यू के हिसाब से कॉपी किए जाते हैं. इसका मतलब है कि पैरामीटर कॉपी किए जाते हैं. डेटा के बड़े हिस्सों या प्रोसेस के बीच शेयर किए जाने वाले डेटा (जैसे, सिंक फ़ेंस) को मैनेज करने के लिए, फ़ाइल डिस्क्रिप्टर का इस्तेमाल किया जाता है. ये डिस्क्रिप्टर, हमेशा मौजूद रहने वाले ऑब्जेक्ट पर ले जाते हैं: ashmem शेयर की गई मेमोरी, असल फ़ाइलों या किसी भी ऐसी चीज़ के लिए इस्तेमाल किया जाता है जो फ़ाइल डिस्क्रिप्टर के पीछे छिप सकती है. बाइंडर ड्राइवर, फ़ाइल डिस्क्रिप्टर को दूसरी प्रोसेस में डुप्लीकेट करता है.

native_handle_t

Android, native_handle_t के साथ काम करता है. यह libcutils में बताए गए हैंडल के सामान्य कॉन्सेप्ट का नाम है.

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;

नेटिव हैंडल, ints और फ़ाइल डिस्क्रिप्टर का एक कलेक्शन होता है, जिसे वैल्यू के हिसाब से पास किया जाता है. किसी एक फ़ाइल डिस्क्रिप्टर को नेटिव हैंडल में सेव किया जा सकता है. इसमें कोई int और एक फ़ाइल डिस्क्रिप्टर नहीं होना चाहिए. handle प्राइमटिव टाइप के साथ एन्कैप्सुलेट किए गए नेटिव हैंडल का इस्तेमाल करके हैंडल पास करने से, यह पक्का होता है कि नेटिव हैंडल सीधे HIDL में शामिल किए जाते हैं.

native_handle_t का साइज़ अलग-अलग हो सकता है. इसलिए, इसे सीधे तौर पर किसी स्ट्रक्चर में शामिल नहीं किया जा सकता. हैंडल फ़ील्ड, अलग से असाइन किए गए native_handle_t के लिए पॉइंटर जनरेट करता है.

Android के पुराने वर्शन में, नेटिव हैंडल बनाने के लिए, libcutils में मौजूद उन ही फ़ंक्शन का इस्तेमाल किया जाता था. Android 8.0 और उसके बाद के वर्शन में, इन फ़ंक्शन को अब android::hardware::hidl नेमस्पेस में कॉपी किया जाता है या NDK में ले जाया जाता है. HIDL के अपने-आप जनरेट होने वाले कोड की मदद से, इन फ़ंक्शन को अपने-आप सीरियलाइज़ और डीसीरियलाइज़ किया जाता है. इसके लिए, उपयोगकर्ता के लिखे गए कोड की ज़रूरत नहीं होती.

हैंडल और फ़ाइल डिस्क्रिप्टर का मालिकाना हक

जब किसी ऐसे HIDL इंटरफ़ेस मेथड को कॉल किया जाता है जो hidl_handle ऑब्जेक्ट (टॉप-लेवल या कंपाउंड टाइप का हिस्सा) को पास करता है या दिखाता है, तो उसमें मौजूद फ़ाइल डिस्क्रिप्टर का मालिकाना हक इस तरह होता है:

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

HIDL, Java में हैंडल के साथ काम नहीं करता, क्योंकि Java में हैंडल की सुविधा काम नहीं करती.

साइज़ वाले अरे

HIDL स्ट्रक्चर में साइज़ वाले कलेक्शन के लिए, उनके एलिमेंट किसी भी तरह के हो सकते हैं. स्ट्रक्चर में ये शामिल हो सकते हैं:

struct foo {
uint32_t[3] x; // array is contained in foo
};

स्ट्रिंग

C++ और Java में स्ट्रिंग अलग-अलग दिखती हैं. हालांकि, ट्रांसपोर्ट स्टोरेज टाइप C++ स्ट्रक्चर होता है. ज़्यादा जानकारी के लिए, HIDL C++ डेटा टाइप या HIDL Java डेटा टाइप देखें.

ध्यान दें: किसी स्ट्रिंग को HIDL इंटरफ़ेस (इसमें Java से Java में स्ट्रिंग भेजना भी शामिल है) के ज़रिए Java में भेजने या उससे पाने पर, कैरेक्टर सेट में बदलाव होता है. ऐसा हो सकता है कि इस बदलाव में ओरिजनल एन्कोडिंग न बच पाए.

vec<T> टाइप का टेंप्लेट

vec<T> टेंप्लेट, वैरिएबल साइज़ के बफ़र को दिखाता है. इसमें T के इंस्टेंस होते हैं.

T इनमें से कोई एक हो सकता है:

  • प्राइमिटिव टाइप (उदाहरण के लिए, uint32_t)
  • स्ट्रिंग
  • उपयोगकर्ता के तय किए गए एनम
  • उपयोगकर्ता के तय किए गए स्ट्रक्चर
  • इंटरफ़ेस या interface कीवर्ड (vec<IFoo>, vec<interface> सिर्फ़ टॉप-लेवल पैरामीटर के तौर पर काम करता है)
  • हैंडल
  • bitfield<U>
  • vec<U>, जहां U इंटरफ़ेस को छोड़कर इस सूची में शामिल है (उदाहरण के लिए, vec<vec<IFoo>> काम नहीं करता)
  • U[] (U का साइज़ वाला कलेक्शन), जहां U इस सूची में शामिल है, लेकिन इंटरफ़ेस नहीं

उपयोगकर्ता के तय किए गए टाइप

इस सेक्शन में, उपयोगकर्ता के तय किए गए टाइप के बारे में बताया गया है.

Enum

HIDL में, बिना नाम वाले एनम की सुविधा काम नहीं करती. इसके अलावा, HIDL में मौजूद एनम, C++11 से मिलते-जुलते हैं:

enum name : type { enumerator , enumerator = constexpr ,   }

बेस एनम को HIDL में, पूर्णांक के किसी एक टाइप के हिसाब से तय किया जाता है. अगर किसी पूर्णांक टाइप के आधार पर, किसी एनम के पहले एनोमेरेटर के लिए कोई वैल्यू तय नहीं की गई है, तो वैल्यू डिफ़ॉल्ट रूप से 0 हो जाती है. अगर बाद में जोड़े जाने वाले एनोमेरेटर के लिए कोई वैल्यू नहीं दी गई है, तो वैल्यू डिफ़ॉल्ट रूप से पिछली वैल्यू के साथ एक हो जाती है. उदाहरण के लिए:

// RED == 0
// BLUE == 4 (GREEN + 1)
enum Color : uint32_t { RED, GREEN = 3, BLUE }

किसी एनम को पहले से तय किए गए एनम से भी इनहेरिट किया जा सकता है. अगर किसी चाइल्ड एनम (इस मामले में FullSpectrumColor) के पहले एनोमेरेटर के लिए कोई वैल्यू नहीं दी गई है, तो यह डिफ़ॉल्ट रूप से, पैरंट एनम के आखिरी एनोमेरेटर की वैल्यू के साथ-साथ एक हो जाती है. उदाहरण के लिए:

// ULTRAVIOLET == 5 (Color:BLUE + 1)
enum FullSpectrumColor : Color { ULTRAVIOLET }

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

एनम की वैल्यू को कोलन सिंटैक्स के साथ रेफ़र किया जाता है, न कि नेस्ट किए गए टाइप के तौर पर बिंदु सिंटैक्स के साथ. इसका सिंटैक्स Type:VALUE_NAME है. अगर वैल्यू का रेफ़रंस, एक ही टाइप या चाइल्ड टाइप में दिया गया है, तो टाइप की जानकारी देने की ज़रूरत नहीं है. उदाहरण:

enum Grayscale : uint32_t { BLACK = 0, WHITE = BLACK + 1 };
enum Color : Grayscale { RED = WHITE + 1 };
enum Unrelated : uint32_t { FOO = Color:RED + 1 };

Android 10 से, एन्सम में एक len एट्रिब्यूट होता है. इसका इस्तेमाल, कॉन्स्टेंट एक्सप्रेशन में किया जा सकता है. MyEnum::len, उस एनोटेशन में मौजूद एंट्री की कुल संख्या है. यह वैल्यू, वैल्यू की कुल संख्या से अलग होती है. वैल्यू डुप्लीकेट होने पर, यह संख्या कम हो सकती है.

Struct

HIDL में, बिना नाम वाले स्ट्रक्चर काम नहीं करते. इसके अलावा, HIDL में स्ट्रक्चर, C के बहुत मिलते-जुलते होते हैं.

HIDL, वैरिएबल-लेंथ डेटा स्ट्रक्चर के साथ काम नहीं करता. ये स्ट्रक्चर, पूरी तरह से किसी स्ट्रक्चर में होते हैं. इसमें, तय लंबाई वाला ऐरे शामिल होता है, जिसका इस्तेमाल कभी-कभी C/C++ में किसी स्ट्रक्चर के आखिरी फ़ील्ड के तौर पर किया जाता है. कभी-कभी इसे [0] साइज़ के साथ देखा जाता है. HIDL vec<T>, डाइनैमिक साइज़ वाले ऐरे को दिखाता है. इनमें डेटा को अलग बफ़र में सेव किया जाता है. ऐसे इंस्टेंस को struct में vec<T> के इंस्टेंस के साथ दिखाया जाता है.

इसी तरह, string को struct में शामिल किया जा सकता है (इससे जुड़े बफ़र अलग-अलग होते हैं). जनरेट किए गए C++ में, HIDL हैंडल टाइप के इंस्टेंस को असली नेटिव हैंडल के पॉइंटर के ज़रिए दिखाया जाता है, क्योंकि डेटा टाइप के इंस्टेंस की लंबाई अलग-अलग होती है.

Union

HIDL में, बिना नाम वाले यूनियन का इस्तेमाल नहीं किया जा सकता. इसके अलावा, यूनियन C के जैसे ही होते हैं.

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

union UnionType {
uint32_t a;
//  vec<uint32_t> r;  // Error: can't contain a vec<T>
uint8_t b;1
};
fun8(UnionType info); // Legal

यूनियन को स्ट्रक्चर के अंदर भी घोषित किया जा सकता है. उदाहरण के लिए:

struct MyStruct {
    union MyUnion {
      uint32_t a;
      uint8_t b;
    }; // declares type but not member

    union MyUnion2 {
      uint32_t a;
      uint8_t b;
    } data; // declares type but not member
  }