एचएएल इंटरफेस बनाना

फ्रेमवर्क को सशर्त रूप से संकलित करने के लिए उपयोग किए जाने वाले सभी बिल्ड फ़्लैग का वर्णन करने के लिए आपको HIDL का उपयोग करना चाहिए। प्रासंगिक बिल्ड फ़्लैग को समूहीकृत किया जाना चाहिए और एक .hal फ़ाइल में शामिल किया जाना चाहिए। कॉन्फ़िगरेशन आइटम निर्दिष्ट करने के लिए HIDL का उपयोग करने से निम्नलिखित लाभ शामिल हैं:

  • संस्करणबद्ध (नए कॉन्फ़िगरेशन आइटम जोड़ने के लिए, विक्रेताओं/ओईएम को स्पष्ट रूप से एचएएल का विस्तार करना होगा)
  • अच्छी तरह से प्रलेखित
  • SELinux का उपयोग करके अभिगम नियंत्रण
  • विक्रेता परीक्षण सूट के माध्यम से कॉन्फ़िगरेशन आइटम के लिए विवेक जांच (सीमा जांच, वस्तुओं के बीच अंतर-निर्भरता जांच, आदि)
  • C++ और Java दोनों में स्वचालित रूप से जेनरेट की गई API

फ़्रेमवर्क द्वारा उपयोग किए गए बिल्ड फ़्लैग की पहचान करना

फ्रेमवर्क को सशर्त रूप से संकलित करने के लिए उपयोग की जाने वाली बिल्ड कॉन्फ़िगरेशन की पहचान करके प्रारंभ करें, फिर सेट को छोटा करने के लिए अप्रचलित कॉन्फ़िगरेशन को छोड़ दें। उदाहरण के लिए, surfaceflinger के लिए बिल्ड फ़्लैग के निम्नलिखित सेट की पहचान की गई है:

  • TARGET_USES_HWC2
  • TARGET_BOARD_PLATFORM
  • TARGET_DISABLE_TRIPLE_BUFFERING
  • TARGET_FORCE_HWC_FOR_VIRTUAL_DISPLAYS
  • NUM_FRAMEBUFFER_SURFACE_BUFFERS
  • TARGET_RUNNING_WITHOUT_SYNC_FRAMEWORK
  • VSYNC_EVENT_PHASE_OFFSET_NS
  • SF_VSYNC_EVENT_PHASE_OFFSET_NS
  • PRESENT_TIME_OFFSET_FROM_VSYNC_NS
  • MAX_VIRTUAL_DISPLAY_DIMENSION

एचएएल इंटरफ़ेस बनाना

किसी सबसिस्टम के लिए बिल्ड कॉन्फ़िगरेशन को HAL इंटरफ़ेस के माध्यम से एक्सेस किया जाता है, जबकि कॉन्फ़िगरेशन मान देने के लिए इंटरफ़ेस को HAL पैकेज android.hardware.configstore (वर्तमान में संस्करण 1.0 पर) में समूहीकृत किया जाता है। उदाहरण के लिए, hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal में surfaceflinger के लिए एक एचएएल इंटरफ़ेस फ़ाइल बनाने के लिए:

package android.hardware.configstore@1.0;

interface ISurfaceFlingerConfigs {
    // TO-BE-FILLED-BELOW
};

.hal फ़ाइल बनाने के बाद, Android.bp और Android.mk फ़ाइलों में नई .hal फ़ाइल जोड़ने के लिए hardware/interfaces/update-makefiles.sh चलाएँ।

बिल्ड फ़्लैग के लिए फ़ंक्शंस जोड़ना

प्रत्येक बिल्ड फ़्लैग के लिए, इंटरफ़ेस में एक नया फ़ंक्शन जोड़ें। उदाहरण के लिए, hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal में:

interface ISurfaceFlingerConfigs {
    disableTripleBuffering() generates(OptionalBool ret);
    forceHwcForVirtualDisplays() generates(OptionalBool ret);
    enum NumBuffers: uint8_t {
        USE_DEFAULT = 0,
        TWO = 2,
        THREE = 3,
    };
    numFramebufferSurfaceBuffers() generates(NumBuffers ret);
    runWithoutSyncFramework() generates(OptionalBool ret);
    vsyncEventPhaseOffsetNs generates (OptionalUInt64 ret);
    presentTimeOffsetFromSyncNs generates (OptionalUInt64 ret);
    maxVirtualDisplayDimension() generates(OptionalInt32 ret);
};

कोई फ़ंक्शन जोड़ते समय:

  • नामों के साथ संक्षिप्त रहें. मेकफ़ाइल वेरिएबल नामों को फ़ंक्शन नामों में परिवर्तित करने से बचें और ध्यान रखें कि TARGET_ और BOARD_ उपसर्ग अब आवश्यक नहीं हैं।
  • टिप्पणी करें। डेवलपर्स को कॉन्फिग आइटम के उद्देश्य को समझने में मदद करें कि यह फ्रेमवर्क व्यवहार, वैध मूल्यों और अन्य प्रासंगिक जानकारी को कैसे बदलता है।

फ़ंक्शन रिटर्न प्रकार Optional[Bool|String|Int32|UInt32|Int64|UInt64] हो सकते हैं। प्रकारों को उसी निर्देशिका में types.hal में परिभाषित किया जाता है और आदिम मानों को एक फ़ील्ड के साथ लपेटा जाता है जो इंगित करता है कि मान HAL द्वारा निर्दिष्ट किया गया है या नहीं; यदि नहीं, तो डिफ़ॉल्ट मान का उपयोग किया जाता है।

struct OptionalString {
    bool specified;
    string value;
};

जब उचित हो, उस एनम को परिभाषित करें जो कॉन्फ़िगरेशन आइटम के प्रकार का सबसे अच्छा प्रतिनिधित्व करता है और उस एनम को रिटर्न प्रकार के रूप में उपयोग करें। उपरोक्त उदाहरण में, NumBuffers enum को मान्य मानों की संख्या को सीमित करने के लिए परिभाषित किया गया है। ऐसे कस्टम डेटा प्रकारों को परिभाषित करते समय, यह दर्शाने के लिए एक फ़ील्ड या एनम मान जोड़ें (उदाहरण के लिए, USE_DEFAULT ) कि क्या मान HAL द्वारा निर्दिष्ट है/नहीं है।

एचआईडीएल में एकल बिल्ड फ़्लैग का एकल फ़ंक्शन बनना अनिवार्य नहीं है। मॉड्यूल मालिक वैकल्पिक रूप से निकट से संबंधित बिल्ड फ़्लैग को एक संरचना में एकत्रित कर सकते हैं और एक फ़ंक्शन रख सकते हैं जो उस संरचना को लौटाता है (ऐसा करने से फ़ंक्शन कॉल की संख्या कम हो सकती है)।

उदाहरण के लिए, hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal में दो बिल्ड फ़्लैग को एक ही संरचना में एकत्रित करने का एक विकल्प है:

 interface ISurfaceFlingerConfigs {
    // other functions here
    struct SyncConfigs {
        OptionalInt64 vsyncEventPhaseoffsetNs;
        OptionalInt64 presentTimeoffsetFromSyncNs;
    };
    getSyncConfigs() generates (SyncConfigs ret);
    // other functions here
};

एकल एचएएल फ़ंक्शन के विकल्प

सभी बिल्ड फ़्लैग के लिए एकल HAL फ़ंक्शन का उपयोग करने के विकल्प के रूप में, HAL इंटरफ़ेस getBoolean(string key) और getInteger(string key) जैसे सरल फ़ंक्शन भी प्रदान करता है। वास्तविक key=value जोड़े अलग-अलग फ़ाइलों में संग्रहीत होते हैं और एचएएल सेवा उन फ़ाइलों को पढ़कर/पार्स करके मान प्रदान करती है।

हालांकि इस दृष्टिकोण को परिभाषित करना आसान है, इसमें एचआईडीएल द्वारा प्रदान किए गए लाभ (प्रबलित संस्करण, दस्तावेज़ीकरण में आसानी, पहुंच नियंत्रण) शामिल नहीं हैं और इसलिए इसकी अनुशंसा नहीं की जाती है।

एकल और एकाधिक इंटरफ़ेस

कॉन्फ़िगरेशन आइटम के लिए HAL इंटरफ़ेस का डिज़ाइन दो विकल्प प्रस्तुत करता है:

  • एक एकल इंटरफ़ेस जो सभी कॉन्फ़िगरेशन आइटम को कवर करता है
  • एकाधिक इंटरफ़ेस, जिनमें से प्रत्येक संबंधित कॉन्फ़िगरेशन आइटम का एक सेट शामिल करता है

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

इन समस्याओं के कारण, एंड्रॉइड संबंधित कॉन्फ़िगरेशन आइटम के समूह के लिए एकल एचएएल इंटरफ़ेस के साथ कई इंटरफेस का उपयोग करता है। उदाहरण के लिए, surfaceflinger -संबंधित कॉन्फ़िगरेशन आइटम के लिए ISurfaceflingerConfigs , और ब्लूटूथ-संबंधित कॉन्फ़िगरेशन आइटम के लिए IBluetoothConfigs