आपको एचआईडीएल का इस्तेमाल करके, उन सभी बिल्ड फ़्लैग के बारे में बताना होगा जिनका इस्तेमाल फ़्रेमवर्क को शर्तों के साथ कंपाइल करने के लिए किया जाता है. काम के बिल्ड फ़्लैग को ग्रुप किया जाना चाहिए और उन्हें एक ही .hal
फ़ाइल में शामिल किया जाना चाहिए. कॉन्फ़िगरेशन आइटम के लिए एचआईडीएल का इस्तेमाल करने से ये फ़ायदे मिलते हैं:
- वर्शन किया गया (नए कॉन्फ़िगरेशन आइटम जोड़ने के लिए, वेंडर/ओईएम को HAL को साफ़ तौर पर बढ़ाना होगा)
- अच्छी तरह से दस्तावेज़ बनाया गया हो
- SELinux का इस्तेमाल करके ऐक्सेस कंट्रोल करना
- वेंडर टेस्ट सुइट की मदद से, कॉन्फ़िगरेशन आइटम की जांच करना (रेंज की जांच, आइटम के बीच इंटर-डिपेंडेंसी की जांच वगैरह)
- C++ और Java, दोनों में अपने-आप जनरेट होने वाले एपीआई
फ़्रेमवर्क के इस्तेमाल किए गए बिल्ड फ़्लैग की पहचान करना
शुरुआत में, उन बिल्ड कॉन्फ़िगरेशन की पहचान करें जिनका इस्तेमाल फ़्रेमवर्क को शर्तों के साथ कंपाइल करने के लिए किया जाता है. इसके बाद, सेट को छोटा करने के लिए पुराने कॉन्फ़िगरेशन को छोड़ दें. उदाहरण के लिए,
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 वर्शन पर है.
उदाहरण के लिए, surfaceflinger
के लिए एचएएल इंटरफ़ेस फ़ाइल बनाने के लिए, hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
में:
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; };
जब ज़रूरी हो, तब उस enum को तय करें जो कॉन्फ़िगरेशन आइटम के टाइप को सबसे सही तरीके से दिखाता है. साथ ही, उस enum को रिटर्न टाइप के तौर पर इस्तेमाल करें. ऊपर दिए गए उदाहरण में, NumBuffers
enum को मान्य वैल्यू की संख्या सीमित करने के लिए तय किया गया है. ऐसे कस्टम डेटा टाइप तय करते समय, एक फ़ील्ड या enum वैल्यू (उदाहरण के लिए, USE_DEFAULT
) जोड़ें. इससे यह पता चलेगा कि HAL ने वैल्यू तय की है या नहीं.
यह ज़रूरी नहीं है कि एक बिल्ड फ़्लैग, HIDL में एक फ़ंक्शन बन जाए. मॉड्यूल के मालिक, मिलते-जुलते बिल्ड फ़्लैग को किसी स्ट्रक्चर में इकट्ठा कर सकते हैं. साथ ही, उनके पास ऐसा फ़ंक्शन हो सकता है जो उस स्ट्रक्चर को दिखाता हो. ऐसा करने से, फ़ंक्शन कॉल की संख्या कम हो सकती है.
उदाहरण के लिए, 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 सेवा उन फ़ाइलों को पढ़कर/पार्स करके वैल्यू देती है.
इस तरीके को आसानी से तय किया जा सकता है. हालांकि, इसमें एचआईडीएल से मिलने वाले फ़ायदे शामिल नहीं हैं. जैसे, वर्शनिंग लागू करना, दस्तावेज़ बनाना आसान होना, और ऐक्सेस कंट्रोल. इसलिए, इसे इस्तेमाल करने का सुझाव नहीं दिया जाता.
सिंगल और मल्टीपल इंटरफ़ेस
कॉन्फ़िगरेशन आइटम के लिए एचएएल इंटरफ़ेस के डिज़ाइन में दो विकल्प होते हैं:
- एक ऐसा इंटरफ़ेस जिसमें कॉन्फ़िगरेशन के सभी आइटम शामिल हों
- कई इंटरफ़ेस, जिनमें से हर एक कॉन्फ़िगरेशन से जुड़े आइटम के सेट को कवर करता है
एक इंटरफ़ेस का इस्तेमाल करना आसान होता है. हालांकि, एक ही फ़ाइल में ज़्यादा कॉन्फ़िगरेशन आइटम जोड़ने पर, इसे मैनेज करना मुश्किल हो सकता है. इसके अलावा, ऐक्सेस कंट्रोल की सुविधा भी बेहतर नहीं है. इसलिए, जिस प्रोसेस को इंटरफ़ेस का ऐक्सेस दिया जाता है वह सभी कॉन्फ़िगरेशन आइटम को पढ़ सकती है. कॉन्फ़िगरेशन आइटम के कुछ हिस्से का ऐक्सेस नहीं दिया जा सकता. इसके अलावा, अगर ऐक्सेस नहीं दिया जाता है, तो कॉन्फ़िगरेशन आइटम नहीं पढ़े जा सकते.
इन समस्याओं की वजह से, Android एक ही HAL इंटरफ़ेस के साथ कई इंटरफ़ेस का इस्तेमाल करता है. यह इंटरफ़ेस, कॉन्फ़िगरेशन से जुड़े आइटम के ग्रुप के लिए होता है. उदाहरण के लिए, surfaceflinger
से जुड़े कॉन्फ़िगरेशन आइटम के लिए ISurfaceflingerConfigs
और ब्लूटूथ से जुड़े कॉन्फ़िगरेशन आइटम के लिए IBluetoothConfigs
.