HIDL

एचएएल और उसके उपयोगकर्ताओं के बीच इंटरफेस को निर्दिष्ट करने के लिए एचएएल इंटरफ़ेस परिभाषा भाषा या एचआईडीएल एक इंटरफ़ेस विवरण भाषा (आईडीएल) है। HIDL इंटरफेस और पैकेज में एकत्रित प्रकार और विधि कॉल निर्दिष्ट करने की अनुमति देता है। अधिक मोटे तौर पर, एचआईडीएल कोडबेस के बीच संचार के लिए एक प्रणाली है जिसे स्वतंत्र रूप से संकलित किया जा सकता है। Android 10 के रूप में, HIDL को पदावनत कर दिया गया है और Android हर जगह AIDL का उपयोग करने के लिए माइग्रेट कर रहा है।

HIDL का उपयोग अंतर-प्रक्रिया संचार (IPC) के लिए किया जाना है। एचडीएल के साथ बनाए गए एचएएल को बाइंडराइज्ड एचएएल कहा जाता है, जिसमें वे बाइंडर इंटर-प्रोसेस कम्युनिकेशन (आईपीसी) कॉल का उपयोग करके अन्य आर्किटेक्चर परतों के साथ संवाद कर सकते हैं। Binderized HALs का उपयोग करने वाले क्लाइंट से अलग प्रक्रिया में चलते हैं। पुस्तकालयों के लिए जिन्हें एक प्रक्रिया से जोड़ा जाना चाहिए, पासथ्रू मोड भी उपलब्ध है (जावा में समर्थित नहीं है)।

एचआईडीएल डेटा संरचनाओं और विधि हस्ताक्षरों को निर्दिष्ट करता है, जो इंटरफेस (एक वर्ग के समान) में व्यवस्थित होते हैं जो संकुल में एकत्र किए जाते हैं। HIDL का सिंटैक्स C++ और Java प्रोग्रामर्स के लिए जाना-पहचाना लगता है, लेकिन कीवर्ड्स के एक अलग सेट के साथ। HIDL जावा-शैली के एनोटेशन का भी उपयोग करता है।

शब्दावली

यह खंड निम्नलिखित एचआईडीएल-संबंधित शर्तों का उपयोग करता है:

बाँधना इंगित करता है कि HIDL का उपयोग प्रक्रियाओं के बीच दूरस्थ प्रक्रिया कॉल के लिए किया जा रहा है, जिसे बाइंडर जैसी तंत्र पर लागू किया गया है। पासथ्रू भी देखें।
कॉलबैक, अतुल्यकालिक एचएएल उपयोगकर्ता द्वारा प्रदान किया गया इंटरफ़ेस, एचएएल (एचआईडीएल विधि का उपयोग करके) को पास किया गया, और एचएएल द्वारा किसी भी समय डेटा वापस करने के लिए बुलाया गया।
कॉलबैक, तुल्यकालिक क्लाइंट को सर्वर के HIDL विधि कार्यान्वयन से डेटा लौटाता है। उन विधियों के लिए उपयोग नहीं किया जाता है जो शून्य या एक आदिम मान लौटाते हैं।
ग्राहक प्रक्रिया जो किसी विशेष इंटरफ़ेस के तरीकों को बुलाती है। एक एचएएल या एंड्रॉइड फ्रेमवर्क प्रक्रिया एक इंटरफ़ेस का क्लाइंट और दूसरे का सर्वर हो सकता है। पासथ्रू भी देखें।
फैली एक इंटरफ़ेस को इंगित करता है जो अन्य इंटरफ़ेस में विधियों और/या प्रकारों को जोड़ता है। एक इंटरफ़ेस केवल एक अन्य इंटरफ़ेस का विस्तार कर सकता है। उसी पैकेज नाम में मामूली संस्करण वृद्धि के लिए या पुराने पैकेज पर निर्माण करने के लिए एक नए पैकेज (उदाहरण के लिए एक विक्रेता विस्तार) के लिए उपयोग किया जा सकता है।
उत्पन्न करता है एक इंटरफ़ेस विधि इंगित करता है जो क्लाइंट को मान देता है। एक गैर-आदिम मान, या एक से अधिक मान वापस करने के लिए, एक तुल्यकालिक कॉलबैक फ़ंक्शन उत्पन्न होता है।
इंटरफेस तरीकों और प्रकारों का संग्रह। सी ++ या जावा में कक्षा में अनुवादित। इंटरफ़ेस में सभी विधियों को एक ही दिशा में कहा जाता है: क्लाइंट प्रक्रिया सर्वर प्रक्रिया द्वारा कार्यान्वित विधियों को कॉल करती है।
एक तरफ़ा रास्ता जब एक HIDL विधि पर लागू किया जाता है, तो यह इंगित करता है कि विधि कोई मान नहीं देती है और ब्लॉक नहीं करती है।
पैकेट एक संस्करण साझा करने वाले इंटरफेस और डेटा प्रकारों का संग्रह।
निकासी HIDL का मोड जिसमें सर्वर एक साझा लाइब्रेरी है, क्लाइंट द्वारा dlopen एड। पासथ्रू मोड में, क्लाइंट और सर्वर एक ही प्रक्रिया हैं लेकिन अलग-अलग कोडबेस हैं। केवल HIDL मॉडल में लीगेसी कोडबेस लाने के लिए उपयोग किया जाता है। बाइंडराइज़्ड भी देखें।
सर्वर प्रक्रिया जो एक इंटरफ़ेस के तरीकों को लागू करती है। पासथ्रू भी देखें।
यातायात HIDL इन्फ्रास्ट्रक्चर जो सर्वर और क्लाइंट के बीच डेटा को स्थानांतरित करता है।
संस्करण एक पैकेज का संस्करण। दो पूर्णांक, प्रमुख और मामूली से मिलकर बनता है। मामूली संस्करण वृद्धि प्रकार और विधियों को जोड़ सकती है (लेकिन परिवर्तित नहीं)।

एचआईडीएल डिजाइन

एचआईडीएल का लक्ष्य यह है कि एचएएल के पुनर्निर्माण के बिना एंड्रॉइड ढांचे को बदला जा सकता है। एचएएल को वेंडर या एसओसी निर्माताओं द्वारा बनाया जाएगा और डिवाइस पर एक /vendor विभाजन में रखा जाएगा, जिससे एंड्रॉइड फ्रेमवर्क को अपने स्वयं के विभाजन में एचएएल को फिर से संकलित किए बिना ओटीए के साथ प्रतिस्थापित किया जा सकेगा।

HIDL डिज़ाइन निम्नलिखित चिंताओं को संतुलित करता है:

  • इंटरऑपरेबिलिटी । विभिन्न आर्किटेक्चर, टूलचेन्स और बिल्ड कॉन्फ़िगरेशन के साथ संकलित की जा सकने वाली प्रक्रियाओं के बीच भरोसेमंद इंटरऑपरेबल इंटरफेस बनाएं। HIDL इंटरफ़ेस संस्करणित हैं और प्रकाशित होने के बाद इन्हें बदला नहीं जा सकता है।
  • दक्षता । HIDL कॉपी ऑपरेशंस की संख्या को कम करने की कोशिश करता है। एचआईडीएल-परिभाषित डेटा सी ++ मानक लेआउट डेटा संरचनाओं में सी ++ कोड को वितरित किया जाता है जिसका उपयोग अनपॅकिंग के बिना किया जा सकता है। HIDL साझा मेमोरी इंटरफेस भी प्रदान करता है और, क्योंकि RPC स्वाभाविक रूप से कुछ धीमी होती है, HIDL RPC कॉल का उपयोग किए बिना डेटा स्थानांतरित करने के दो तरीकों का समर्थन करता है: साझा मेमोरी और एक तेज़ संदेश कतार (FMQ)।
  • सहज । HIDL केवल RPC के लिए मापदंडों in उपयोग करके मेमोरी स्वामित्व के कांटेदार मुद्दों से बचता है ( एंड्रॉइड इंटरफ़ेस डेफिनिशन लैंग्वेज (AIDL) देखें); कॉलबैक फ़ंक्शन के माध्यम से वे मान लौटाए जाते हैं जिन्हें विधियों से कुशलतापूर्वक वापस नहीं किया जा सकता है। स्थानांतरण के लिए न तो एचआईडीएल में डेटा पास करना और न ही एचआईडीएल से डेटा प्राप्त करना डेटा के स्वामित्व को बदलता है - स्वामित्व हमेशा कॉलिंग फ़ंक्शन के साथ रहता है। डेटा को केवल कॉल किए गए फ़ंक्शन की अवधि के लिए बने रहने की आवश्यकता होती है और कॉल किए गए फ़ंक्शन रिटर्न के तुरंत बाद नष्ट हो सकता है।

पासथ्रू मोड का उपयोग करना

Android के पुराने संस्करणों को Android O में चलाने वाले उपकरणों को अपडेट करने के लिए, आप पारंपरिक (और विरासत) दोनों HALs को एक नए HIDL इंटरफ़ेस में लपेट सकते हैं जो HAL को बाइंडराइज़्ड और समान-प्रक्रिया (पासथ्रू) मोड में कार्य करता है। यह रैपिंग HAL और Android फ्रेमवर्क दोनों के लिए पारदर्शी है।

पासथ्रू मोड केवल C++ क्लाइंट और कार्यान्वयन के लिए उपलब्ध है। एंड्रॉइड के पुराने संस्करणों को चलाने वाले उपकरणों में जावा में लिखे गए एचएएल नहीं होते हैं, इसलिए जावा एचएएल स्वाभाविक रूप से बाइंडरीकृत होते हैं।

जब एक .hal फ़ाइल संकलित की जाती है, hidl-gen बाइंडर संचार के लिए उपयोग किए जाने वाले हेडर के अतिरिक्त एक अतिरिक्त पासथ्रू हेडर फ़ाइल BsFoo.h उत्पन्न करता है; यह हेडर कार्यों को dlopen ed होने के लिए परिभाषित करता है। चूंकि पासथ्रू एचएएल उसी प्रक्रिया में चलते हैं जिसमें उन्हें बुलाया जाता है, ज्यादातर मामलों में प्रत्यक्ष फ़ंक्शन कॉल (समान थ्रेड) द्वारा पासथ्रू विधियों का आह्वान किया जाता है। oneway तरीके अपने स्वयं के थ्रेड में चलते हैं क्योंकि उनका उद्देश्य HAL द्वारा उन्हें प्रोसेस करने के लिए प्रतीक्षा करना नहीं है (इसका मतलब है कि कोई भी HAL जो पासथ्रू मोड में oneway विधियों का उपयोग करता है, थ्रेड-सुरक्षित होना चाहिए)।

एक IFoo.hal दिया गया है, BsFoo.h अतिरिक्त सुविधाएँ प्रदान करने के लिए oneway जनरेट किए गए तरीकों को लपेटता है (जैसे कि एक तरफ़ा लेन-देन दूसरे थ्रेड में चलाना)। यह फ़ाइल BpFoo.h के समान है, हालाँकि बाइंडर का उपयोग करके IPC कॉल पास करने के बजाय, वांछित फ़ंक्शन सीधे लागू किए जाते हैं। एचएएल के भविष्य के कार्यान्वयन कई कार्यान्वयन प्रदान कर सकते हैं , जैसे कि फूफ़ास्ट एचएएल और फूएक्यूरेट एचएएल। ऐसे मामलों में, प्रत्येक अतिरिक्त कार्यान्वयन के लिए एक फ़ाइल बनाई जाएगी (उदाहरण के लिए, PTFooFast.cpp और PTFooAccurate.cpp )।

पासथ्रू एचएएल को बाइंडराइज़ करना

आप पासथ्रू मोड का समर्थन करने वाले एचएएल कार्यान्वयन को बाइंडराइज़ कर सकते हैं। एक एचएएल इंटरफ़ेस abcd@MN::IFoo दिया गया है, दो पैकेज बनाए गए हैं:

  • abcd@MN::IFoo-impl । एचएएल के कार्यान्वयन को समाहित करता है और IFoo* HIDL_FETCH_IFoo(const char* name) फ़ंक्शन को प्रदर्शित करता है। लीगेसी उपकरणों पर, यह पैकेज dlopen ed है और कार्यान्वयन HIDL_FETCH_IFoo का उपयोग करके तत्काल किया जाता है। आप hidl-gen और -Lc++-impl और -Landroidbp-impl का उपयोग करके आधार कोड उत्पन्न कर सकते हैं।
  • abcd@MN::IFoo-service । पासथ्रू एचएएल को खोलता है और खुद को एक बाइंडरीकृत सेवा के रूप में पंजीकृत करता है, जिससे समान एचएएल कार्यान्वयन को पासथ्रू और बाइंडराइज़्ड दोनों के रूप में उपयोग किया जा सकता है।

IFoo प्रकार को देखते हुए, आप IFoo के उदाहरण तक पहुंच प्राप्त करने के लिए sp<IFoo> IFoo::getService(string name, bool getStub) को कॉल कर सकते हैं। यदि getStub सत्य है, तो getService HAL को केवल पासथ्रू मोड में खोलने का प्रयास करता है। यदि getStub गलत है, तो getService एक बाइंडरीकृत सेवा खोजने का प्रयास करता है; यदि यह विफल रहता है, तो यह पासथ्रू सेवा खोजने का प्रयास करता है। getStub पैरामीटर को defaultPassthroughServiceImplementation को छोड़कर कभी भी उपयोग नहीं किया जाना चाहिए। (एंड्रॉइड ओ के साथ लॉन्च होने वाले डिवाइस पूरी तरह से बाइंडराइज्ड डिवाइस हैं, इसलिए पासथ्रू मोड में सेवा खोलने की अनुमति नहीं है।)

एचआईडीएल व्याकरण

डिज़ाइन के अनुसार, HIDL भाषा C के समान है (लेकिन C प्रीप्रोसेसर का उपयोग नहीं करती है)। नीचे वर्णित सभी विराम चिह्न ( = और | के स्पष्ट उपयोग को छोड़कर) व्याकरण का हिस्सा हैं।

नोट: HIDL कोड शैली के विवरण के लिए, कोड शैली मार्गदर्शिका देखें।

  • /** */ एक प्रलेखन टिप्पणी इंगित करता है। इन्हें केवल टाइप, मेथड, फील्ड और एनम वैल्यू डिक्लेरेशन पर लागू किया जा सकता है।
  • /* */ एक बहुपंक्ति टिप्पणी इंगित करता है।
  • // पंक्ति के अंत में एक टिप्पणी इंगित करता है। // के अलावा, न्यूलाइन्स किसी भी अन्य व्हाइटस्पेस के समान हैं।
  • नीचे दिए गए उदाहरण व्याकरण में, // से पंक्ति के अंत तक का पाठ व्याकरण का हिस्सा नहीं है, बल्कि इसके बजाय व्याकरण पर एक टिप्पणी है।
  • [empty] का मतलब है कि शब्द खाली हो सकता है।
  • ? एक शाब्दिक या शब्द का पालन करने का अर्थ है कि यह वैकल्पिक है।
  • ... इंगित किए गए विराम चिह्न के साथ शून्य या अधिक आइटम वाले अनुक्रम को इंगित करता है। एचआईडीएल में कोई विविध तर्क नहीं हैं।
  • अल्पविराम अलग अनुक्रम तत्व।
  • अर्धविराम अंतिम तत्व सहित प्रत्येक तत्व को समाप्त करते हैं।
  • अपरकेस एक गैर-टर्मिनल है।
  • italics एक टोकन परिवार है जैसे integer या identifier (मानक सी पार्सिंग नियम)।
  • constexpr एक सी शैली निरंतर अभिव्यक्ति है (जैसे 1 + 1 और 1L << 3 )।
  • import_name एक पैकेज या इंटरफ़ेस नाम है, जिसे HIDL वर्जनिंग में वर्णित किया गया है।
  • लोअरकेस words शाब्दिक टोकन हैं।

उदाहरण:

ROOT =
    PACKAGE IMPORTS PREAMBLE { ITEM ITEM ... }  // not for types.hal
  | PACKAGE IMPORTS ITEM ITEM...  // only for types.hal; no method definitions

ITEM =
    ANNOTATIONS? oneway? identifier(FIELD, FIELD ...) GENERATES?;
  |  safe_union identifier { UFIELD; UFIELD; ...};
  |  struct identifier { SFIELD; SFIELD; ...};  // Note - no forward declarations
  |  union identifier { UFIELD; UFIELD; ...};
  |  enum identifier: TYPE { ENUM_ENTRY, ENUM_ENTRY ... }; // TYPE = enum or scalar
  |  typedef TYPE identifier;

VERSION = integer.integer;

PACKAGE = package android.hardware.identifier[.identifier[...]]@VERSION;

PREAMBLE = interface identifier EXTENDS

EXTENDS = <empty> | extends import_name  // must be interface, not package

GENERATES = generates (FIELD, FIELD ...)

// allows the Binder interface to be used as a type
// (similar to typedef'ing the final identifier)
IMPORTS =
   [empty]
  |  IMPORTS import import_name;

TYPE =
  uint8_t | int8_t | uint16_t | int16_t | uint32_t | int32_t | uint64_t | int64_t |
 float | double | bool | string
|  identifier  // must be defined as a typedef, struct, union, enum or import
               // including those defined later in the file
|  memory
|  pointer
|  vec<TYPE>
|  bitfield<TYPE>  // TYPE is user-defined enum
|  fmq_sync<TYPE>
|  fmq_unsync<TYPE>
|  TYPE[SIZE]

FIELD =
   TYPE identifier

UFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SFIELD =
   TYPE identifier
  |  safe_union identifier { FIELD; FIELD; ...};
  |  struct identifier { FIELD; FIELD; ...};
  |  union identifier { FIELD; FIELD; ...};
  |  safe_union identifier { FIELD; FIELD; ...} identifier;
  |  struct identifier { FIELD; FIELD; ...} identifier;
  |  union identifier { FIELD; FIELD; ...} identifier;

SIZE =  // Must be greater than zero
     constexpr

ANNOTATIONS =
     [empty]
  |  ANNOTATIONS ANNOTATION

ANNOTATION =
  |  @identifier
  |  @identifier(VALUE)
  |  @identifier(ANNO_ENTRY, ANNO_ENTRY  ...)

ANNO_ENTRY =
     identifier=VALUE

VALUE =
     "any text including \" and other escapes"
  |  constexpr
  |  {VALUE, VALUE ...}  // only in annotations

ENUM_ENTRY =
     identifier
  |  identifier = constexpr