आपको उन सभी बिल्ड फ़्लैग के बारे में बताने के लिए HIDL का इस्तेमाल करना होगा जिनका इस्तेमाल शर्तों के साथ
किसी फ़्रेमवर्क को कंपाइल करने के लिए किया जाता है. काम के बिल्ड फ़्लैग को ग्रुप में रखना और एक ही .hal
फ़ाइल में शामिल करना ज़रूरी है. कॉन्फ़िगरेशन आइटम के बारे में बताने के लिए HIDL का इस्तेमाल करने
के ये फ़ायदे हैं:
- नए कॉन्फ़िगरेशन आइटम जोड़ने के लिए, वेंडर/OEM को साफ़ तौर पर एचएएल का दायरा बढ़ाना होगा
- दस्तावेज़ होने चाहिए
- 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 इंटरफ़ेस से ऐक्सेस किया जाता है. वहीं,
कॉन्फ़िगरेशन वैल्यू देने वाले इंटरफ़ेस को HAL पैकेज
android.hardware.configstore
(फ़िलहाल, 1.0 पर मौजूद है) में ग्रुप किया जाता है.
उदाहरण के लिए, hardware/interfaces/configstore/1.0/ISurfaceFlingerConfigs.hal
में surfaceflinger
के लिए 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); };
फ़ंक्शन जोड़ते समय:
- कम से कम नाम इस्तेमाल करें. Makefile वैरिएबल के नामों को फ़ंक्शन नामों में बदलने से बचें और ध्यान रखें कि
TARGET_
औरBOARD_
प्रीफ़िक्स अब ज़रूरी नहीं हैं. - टिप्पणियां जोड़ें. इससे डेवलपर को कॉन्फ़िगरेशन आइटम का मकसद समझने में मदद मिलती है. साथ ही, यह भी पता चलता है कि इससे फ़्रेमवर्क के काम करने के तरीके, मान्य वैल्यू, और काम की अन्य जानकारी में कैसे बदलाव होता है.
फ़ंक्शन के रिटर्न टाइप
Optional[Bool|String|Int32|UInt32|Int64|UInt64]
हो सकते हैं. उसी डायरेक्ट्री में, types.hal
में अलग-अलग टाइप के बारे में बताया जाता है. साथ ही, प्रिमिटिव वैल्यू को ऐसे फ़ील्ड के साथ रैप करें जिससे पता चलता है कि वैल्यू एचएएल ने तय की है या नहीं. अगर वैल्यू नहीं दी गई है, तो डिफ़ॉल्ट वैल्यू का इस्तेमाल किया जाता है.
struct OptionalString { bool specified; string value; };
जब सही हो, तो ऐसे ईनम के बारे में बताएं जो कॉन्फ़िगरेशन आइटम के टाइप को सबसे सही तरीके से दिखाता हो. साथ ही, उस ईनम का इस्तेमाल रिटर्न टाइप के तौर पर करें. ऊपर दिए गए उदाहरण में, NumBuffers
enum को मान्य वैल्यू की संख्या को सीमित करने के लिए तय किया गया है. ऐसे कस्टम डेटा टाइप तय करते समय, कोई फ़ील्ड या ईनम वैल्यू (उदाहरण के लिए, USE_DEFAULT
) जोड़ें. इससे पता चलेगा कि वैल्यू को एचएएल ने तय किया है या नहीं.
किसी सिंगल बिल्ड फ़्लैग के लिए, 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 फ़ंक्शन के इस्तेमाल के विकल्प के तौर पर, HAL इंटरफ़ेस में getBoolean(string
key)
और getInteger(string key)
जैसे आसान फ़ंक्शन भी मिलते हैं. असल
key=value
पेयर को अलग-अलग फ़ाइलों में सेव किया जाता है और HAL सेवा
उन फ़ाइलों को पढ़कर/पार्स करके वैल्यू देती है.
इस तरीके को समझना आसान है, लेकिन इसमें HIDL से मिलने वाले फ़ायदे शामिल नहीं हैं जैसे कि एचआईडीएल (लागू होने वाला वर्शन, दस्तावेज़ में इस्तेमाल करने में आसानी, ऐक्सेस कंट्रोल). इसलिए, इसका सुझाव नहीं दिया जाता है.
एक और कई इंटरफ़ेस
कॉन्फ़िगरेशन आइटम के लिए HAL इंटरफ़ेस के डिज़ाइन में दो विकल्प हैं:
- एक ऐसा इंटरफ़ेस जिसमें सभी कॉन्फ़िगरेशन आइटम शामिल होते हैं
- कई इंटरफ़ेस, जिनमें से हर इंटरफ़ेस में मिलते-जुलते कॉन्फ़िगरेशन आइटम का सेट शामिल होता है
एक इंटरफ़ेस आसान है, लेकिन इसे बनाए रखना मुश्किल हो सकता है. ऐसा इसलिए होता है, क्योंकि एक फ़ाइल में ज़्यादा कॉन्फ़िगरेशन आइटम जोड़े जाते हैं. इसके अलावा, ऐक्सेस कंट्रोल के लिए बेहतर ऐक्सेस नहीं दिया जाता. इसलिए, जिस प्रोसेस को इंटरफ़ेस का ऐक्सेस दिया जाता है वह सभी कॉन्फ़िगरेशन आइटम को पढ़ सकती है. कॉन्फ़िगरेशन आइटम के कुछ सेट का ऐक्सेस नहीं दिया जा सकता. इसके अलावा, अगर ऐक्सेस नहीं दिया जाता है, तो कॉन्फ़िगरेशन आइटम नहीं पढ़े जा सकते हैं.
इन समस्याओं की वजह से, Android मिलते-जुलते कॉन्फ़िगरेशन आइटम के ग्रुप के लिए, एक ही HAL इंटरफ़ेस वाले कई इंटरफ़ेस इस्तेमाल करता है. उदाहरण के लिए, surfaceflinger
से जुड़े कॉन्फ़िगरेशन आइटम के लिए ISurfaceflingerConfigs
और ब्लूटूथ से जुड़े कॉन्फ़िगरेशन आइटम के लिए IBluetoothConfigs
.