Android 11 में, Android में एचएएल के लिए एआईडीएल का इस्तेमाल करने की सुविधा जोड़ी गई है. इससे, एचआईडीएल के बिना Android के कुछ हिस्सों को लागू किया जा सकता है. जहां भी हो सके, एआईडीएल का इस्तेमाल करने के लिए एचएएल को ट्रांज़िशन करना (जब अपस्ट्रीम एचएएल एचआईडीएल का इस्तेमाल करते हैं, तो एचआईडीएल का इस्तेमाल करना ज़रूरी है).
system.img
जैसे फ़्रेमवर्क कॉम्पोनेंट और vendor.img
जैसे हार्डवेयर कॉम्पोनेंट के बीच कम्यूनिकेट करने के लिए, एआईडीएल का इस्तेमाल करने वाले एचएएल को स्थिर एआईडीएल का इस्तेमाल करना होगा. हालांकि, किसी एक सेगमेंट में एक से दूसरे एचएएल के बीच कम्यूनिकेट करने के लिए, आईपीसी प्रोसेस का इस्तेमाल करने पर कोई पाबंदी नहीं है.
वजह
एआईडीएल, एचआईडीएल से पहले से मौजूद है. इसका इस्तेमाल कई जगहों पर किया जाता है, जैसे कि Android फ़्रेमवर्क कॉम्पोनेंट के बीच या ऐप्लिकेशन में. अब AIDL में स्थिरता की सुविधा उपलब्ध है. इसलिए, एक ही आईपीसी रनटाइम की मदद से पूरे स्टैक को लागू किया जा सकता है. AIDL में, HIDL की तुलना में वर्शनिंग सिस्टम भी बेहतर है. यहां AIDL के कुछ फ़ायदे दिए गए हैं:
- एक ही आईपीसी भाषा का इस्तेमाल करने का मतलब है कि आपको सिर्फ़ एक चीज़ सीखनी है, डीबग करनी है, ऑप्टिमाइज़ करनी है, और सुरक्षित करनी है.
- एआईडीएल, इंटरफ़ेस के मालिकों के लिए, इन-प्लेस वर्शनिंग की सुविधा देता है:
- मालिक, इंटरफ़ेस के आखिर में तरीके या पार्सल किए जा सकने वाले आइटम में फ़ील्ड जोड़ सकते हैं. इसका मतलब है कि सालों के हिसाब से कोड का वर्शन बनाना आसान है. साथ ही, साल दर साल की लागत भी कम होती है. टाइप में बदलाव किया जा सकता है और हर इंटरफ़ेस वर्शन के लिए अतिरिक्त लाइब्रेरी की ज़रूरत नहीं होती.
- एक्सटेंशन इंटरफ़ेस, टाइप सिस्टम के बजाय रन टाइम पर अटैच किए जा सकते हैं. इसलिए, डाउनस्ट्रीम एक्सटेंशन को इंटरफ़ेस के नए वर्शन पर फिर से आधार बनाने की ज़रूरत नहीं है.
- जब कोई डेवलपर अपने मौजूदा AIDL इंटरफ़ेस को स्थिर करने का विकल्प चुनता है, तो उसका इस्तेमाल सीधे तौर पर किया जा सकता है. पहले, इंटरफ़ेस की पूरी कॉपी को HIDL में बनाना पड़ता था.
AIDL रनटाइम के हिसाब से बनाना
AIDL के तीन अलग-अलग बैकएंड हैं: Java, NDK, और CPP. स्थिर AIDL का इस्तेमाल करने के लिए, system/lib*/libbinder.so
पर libbinder
की सिस्टम कॉपी का हमेशा इस्तेमाल करें और /dev/binder
पर बातचीत करें. इसका मतलब है कि vendor
इमेज पर मौजूद कोड के लिए, VNDK की libbinder
का इस्तेमाल नहीं किया जा सकता: इस लाइब्रेरी में अस्थिर C++ API और अस्थिर इंटरनल हैं. इसके बजाय, नेटिव वेंडर कोड को AIDL के एनडीके बैकएंड का इस्तेमाल करना चाहिए. साथ ही, libbinder_ndk
(जो सिस्टम libbinder.so
के साथ काम करता है) और aidl_interface
एंट्री से बनाई गई एनडीके लाइब्रेरी से लिंक करना चाहिए. मॉड्यूल के सटीक नामों के लिए, मॉड्यूल के नाम रखने के नियम देखें.
एआईडीएल एचएएल इंटरफ़ेस लिखना
सिस्टम और वेंडर के बीच किसी एआईडीएल इंटरफ़ेस का इस्तेमाल करने के लिए, इंटरफ़ेस में दो बदलाव करने होंगे:
- हर टाइप की जानकारी को
@VintfStability
के साथ एनोटेट किया जाना चाहिए. aidl_interface
एलान मेंstability: "vintf",
शामिल होना चाहिए.
सिर्फ़ इंटरफ़ेस का मालिक ही इनमें बदलाव कर सकता है.
ये बदलाव करने के बाद, इंटरफ़ेस काम कर सके, इसके लिए VINTF मेनिफ़ेस्ट में होना चाहिए. वीटीएस टेस्ट vts_treble_vintf_vendor_test
का इस्तेमाल करके, इस और इससे जुड़ी ज़रूरी शर्तों की जांच करें. जैसे, यह पुष्टि करना कि रिलीज़ किए गए इंटरफ़ेस फ़्रीज़ हैं. किसी बाइंडर ऑब्जेक्ट को किसी दूसरी प्रोसेस पर भेजने से पहले, NDK बैकएंड में AIBinder_forceDowngradeToLocalStability
, C++ बैकएंड में android::Stability::forceDowngradeToLocalStability
या Java बैकएंड में android.os.Binder#forceDowngradeToSystemStability
को कॉल करके, इन ज़रूरी शर्तों के बिना @VintfStability
इंटरफ़ेस का इस्तेमाल किया जा सकता है.
इसके अलावा, ज़्यादा से ज़्यादा कोड को एक प्लैटफ़ॉर्म से दूसरे प्लैटफ़ॉर्म पर ले जाने के लिए और ग़ैर-ज़रूरी अतिरिक्त लाइब्रेरी जैसी संभावित समस्याओं से बचने के लिए, सीपीपी बैकएंड को बंद करें.
ध्यान दें कि नीचे दिए गए कोड के उदाहरण में backends
का इस्तेमाल सही है, क्योंकि इसमें तीन बैकएंड (Java, NDK, और CPP) हैं. इस कोड में, सीपीपी बैकएंड को बंद करने का तरीका बताया गया है:
aidl_interface: {
...
backends: {
cpp: {
enabled: false,
},
},
}
एआईडीएल एचएएल इंटरफ़ेस ढूंढना
एचएएल के लिए AOSP के स्टेबल एआईडीएल इंटरफ़ेस, aidl
फ़ोल्डर में मौजूद होते हैं. ये फ़ोल्डर, एचआईडीएल इंटरफ़ेस वाली एक ही बेस डायरेक्ट्री में होते हैं:
hardware/interfaces
, आम तौर पर हार्डवेयर से मिलने वाले इंटरफ़ेस के लिए होता है.frameworks/hardware/interfaces
, हार्डवेयर के लिए उपलब्ध कराए गए हाई-लेवल इंटरफ़ेस के लिए है.system/hardware/interfaces
, हार्डवेयर के लिए उपलब्ध कराए गए लोअर लेवल इंटरफ़ेस के लिए है.
एक्सटेंशन इंटरफ़ेस को vendor
या hardware
में मौजूद अन्य hardware/interfaces
सबडायरेक्ट्री में डालें.
एक्सटेंशन इंटरफ़ेस
Android के हर रिलीज़ में, आधिकारिक AOSP इंटरफ़ेस का एक सेट होता है. जब Android पार्टनर इन इंटरफ़ेस में सुविधाएं जोड़ना चाहते हैं, तो उन्हें इनमें सीधे तौर पर बदलाव नहीं करना चाहिए. ऐसा करने से, उनका Android रनटाइम, AOSP Android रनटाइम के साथ काम नहीं करता. इन इंटरफ़ेस में बदलाव करने से बचें, ताकि जीएसआई इमेज काम करती रहे.
एक्सटेंशन दो अलग-अलग तरीकों से रजिस्टर किए जा सकते हैं:
- रनटाइम पर; अटैच किए गए एक्सटेंशन इंटरफ़ेस देखें
- स्टैंडअलोन के तौर पर, दुनिया भर में और VINTF में रजिस्टर किया गया हो
किसी भी तरह का एक्सटेंशन रजिस्टर होने पर, जब वेंडर के हिसाब से (यानी अपस्ट्रीम AOSP का हिस्सा नहीं) कंपोनेंट इंटरफ़ेस का इस्तेमाल करते हैं, तो मर्ज करने से जुड़ी समस्याएं नहीं आती हैं. हालांकि, जब अपस्ट्रीम AOSP कंपोनेंट में डाउनस्ट्रीम बदलाव किए जाते हैं, तो मर्ज करने से जुड़ी समस्याएं आ सकती हैं. इसलिए, इन रणनीतियों का सुझाव दिया जाता है:
- अगली रिलीज़ में, इंटरफ़ेस में जोड़े गए बदलावों को AOSP में अपस्ट्रीम करें.
- अपस्ट्रीम इंटरफ़ेस में जोड़े गए ऐसे बदलाव जिनसे अगले रिलीज़ में, मर्ज करने से जुड़ी समस्याओं के बिना ज़्यादा आसानी से काम किया जा सके.
एक्सटेंशन के लिए पार्स किए जा सकने वाले आइटम: ParcelableHolder
ParcelableHolder
, Parcelable
इंटरफ़ेस का एक इंस्टेंस है. इसमें Parcelable
का एक और इंस्टेंस हो सकता है.
ParcelableHolder
का मुख्य इस्तेमाल, Parcelable
को एक्सटेंसिबल बनाने के लिए किया जाता है.
उदाहरण के लिए, डिवाइस लागू करने वाले लोग, अपनी वैल्यू-ऐड करने वाली सुविधाओं को शामिल करने के लिए, AOSP के तय किए गए Parcelable
, AospDefinedParcelable
को बढ़ाने की उम्मीद करते हैं.
Parcelable
को ज़्यादा फ़ायदेमंद बनाने के लिए, ParcelableHolder
इंटरफ़ेस का इस्तेमाल करें. ParcelableHolder
इंटरफ़ेस में Parcelable
का एक उदाहरण है. अगर Parcelable
में सीधे फ़ील्ड जोड़ने की कोशिश की जाती है, तो इससे गड़बड़ी होती है:
parcelable AospDefinedParcelable {
int a;
String b;
String x; // ERROR: added by a device implementer
int[] y; // added by a device implementer
}
जैसा कि पिछले कोड में देखा गया है, यह तरीका काम नहीं करता, क्योंकि डिवाइस लागू करने वाले व्यक्ति के जोड़े गए फ़ील्ड में, Android के अगले रिलीज़ में Parcelable
में बदलाव होने पर, कोई समस्या हो सकती है.
ParcelableHolder
का इस्तेमाल करके, किसी पार्सल किए जा सकने वाले आइटम का मालिक, Parcelable
के किसी इंस्टेंस में एक्सटेंशन पॉइंट तय कर सकता है:
parcelable AospDefinedParcelable {
int a;
String b;
ParcelableHolder extension;
}
इसके बाद, डिवाइस लागू करने वाले लोग अपने एक्सटेंशन के लिए, Parcelable
का अपना इंस्टेंस तय कर सकते हैं:
parcelable OemDefinedParcelable {
String x;
int[] y;
}
नए Parcelable
इंस्टेंस को ParcelableHolder
फ़ील्ड की मदद से, ओरिजनल Parcelable
से अटैच किया जा सकता है:
// Java
AospDefinedParcelable ap = ...;
OemDefinedParcelable op = new OemDefinedParcelable();
op.x = ...;
op.y = ...;
ap.extension.setParcelable(op);
...
OemDefinedParcelable op = ap.extension.getParcelable(OemDefinedParcelable.class);
// C++
AospDefinedParcelable ap;
OemDefinedParcelable op;
std::shared_ptr<OemDefinedParcelable> op_ptr = make_shared<OemDefinedParcelable>();
ap.extension.setParcelable(op);
ap.extension.setParcelable(op_ptr);
...
std::shared_ptr<OemDefinedParcelable> op_ptr;
ap.extension.getParcelable(&op_ptr);
// NDK
AospDefinedParcelable ap;
OemDefinedParcelable op;
ap.extension.setParcelable(op);
...
std::optional<OemDefinedParcelable> op;
ap.extension.getParcelable(&op);
// Rust
let mut ap = AospDefinedParcelable { .. };
let op = Rc::new(OemDefinedParcelable { .. });
ap.extension.set_parcelable(Rc::clone(&op));
...
let op = ap.extension.get_parcelable::<OemDefinedParcelable>();
एआईडीएल एचएएल सर्वर इंस्टेंस के नाम
आम तौर पर, AIDL HAL सेवाओं के इंस्टेंस का नाम, $package.$type/$instance
फ़ॉर्मैट में होता है. उदाहरण के लिए, वाइब्रेटर HAL का एक इंस्टेंस, android.hardware.vibrator.IVibrator/default
के तौर पर रजिस्टर किया गया है.
एआईडीएल एचएएल सर्वर लिखना
@VintfStability
एआईडीएल सर्वर की जानकारी, VINTF मेनिफ़ेस्ट में दी जानी चाहिए. उदाहरण के लिए:
<hal format="aidl">
<name>android.hardware.vibrator</name>
<version>1</version>
<fqname>IVibrator/default</fqname>
</hal>
ऐसा न करने पर, उन्हें सामान्य तरीके से AIDL सेवा रजिस्टर करनी चाहिए. VTS टेस्ट चलाते समय, यह उम्मीद की जाती है कि एआईडीएल के सभी एचएएल उपलब्ध हों.
AIDL क्लाइंट लिखना
AIDL क्लाइंट को, अपने बारे में संगतता मैट्रिक्स में बताना होगा. उदाहरण के लिए:
<hal format="aidl" optional="true">
<name>android.hardware.vibrator</name>
<version>1-2</version>
<interface>
<name>IVibrator</name>
<instance>default</instance>
</interface>
</hal>
किसी मौजूदा एचएएल को HIDL से AIDL में बदलना
एचआईडीएल इंटरफ़ेस को एआईडीएल में बदलने के लिए, hidl2aidl
टूल का इस्तेमाल करें.
hidl2aidl
की सुविधाएं:
- दिए गए पैकेज के लिए, एचएएल (
.hal
) फ़ाइलों के आधार पर एआईडीएल (.aidl
) फ़ाइलें बनाएं. - सभी बैकएंड चालू करके, बनाए गए नए AIDL पैकेज के लिए बिल्ड नियम बनाएं.
- HIDL टाइप से AIDL टाइप में अनुवाद करने के लिए, Java, CPP, और NDK बैकएंड में अनुवाद करने के तरीके बनाएं.
- ज़रूरी डिपेंडेंसी वाली Translate लाइब्रेरी के लिए, बिल्ड रूल बनाएं.
- स्टैटिक एसर्ट बनाएं, ताकि यह पक्का किया जा सके कि सीपीपी और एनडीके बैकएंड में, HIDL और एआईडीएल एनोमेरेटर की वैल्यू एक ही हों.
HAL फ़ाइलों के पैकेज को AIDL फ़ाइलों में बदलने के लिए, यह तरीका अपनाएं:
system/tools/hidl/hidl2aidl
में मौजूद टूल बनाएं.इस टूल को नए सोर्स से बनाने पर, आपको सबसे बेहतर अनुभव मिलता है. पिछले रिलीज़ के पुराने ब्रैंच पर मौजूद इंटरफ़ेस को बदलने के लिए, नए वर्शन का इस्तेमाल किया जा सकता है:
m hidl2aidl
टूल को आउटपुट डायरेक्ट्री के साथ चलाएं. इसके बाद, उस पैकेज का नाम डालें जिसे बदलना है.
इसके अलावा, जनरेट की गई सभी फ़ाइलों में सबसे ऊपर, लाइसेंस की नई फ़ाइल का कॉन्टेंट जोड़ने के लिए,
-l
आर्ग्युमेंट का इस्तेमाल करें. सही लाइसेंस और तारीख का इस्तेमाल करना न भूलें:hidl2aidl -o <output directory> -l <file with license> <package>
उदाहरण के लिए:
hidl2aidl -o . -l my_license.txt android.hardware.nfc@1.2
जनरेट की गई फ़ाइलों को पढ़ें और कन्वर्ज़न से जुड़ी किसी भी समस्या को ठीक करें:
conversion.log
में ऐसी समस्याएं होती हैं जिन्हें पहले ठीक करना ज़रूरी है.- जनरेट की गई AIDL फ़ाइलों में ऐसी चेतावनियां और सुझाव हो सकते हैं जिन पर कार्रवाई की ज़रूरत हो. ये टिप्पणियां
//
से शुरू होती हैं. - पैकेज को साफ़ करें और उसमें सुधार करें.
- ज़रूरी सुविधाओं के लिए,
@JavaDerive
एनोटेशन देखें. जैसे,toString
याequals
.
सिर्फ़ अपनी ज़रूरत के मुताबिक टारगेट बनाएं:
- ऐसे बैकएंड बंद करें जिनका इस्तेमाल नहीं किया जाएगा. सीपीपी बैकएंड के बजाय, एनडीके बैकएंड का इस्तेमाल करें; एआईडीएल रनटाइम के हिसाब से बनाएं देखें.
- अनुवाद करने वाली लाइब्रेरी या उनसे जनरेट किया गया ऐसा कोड हटाएं जिसका इस्तेमाल नहीं किया जाएगा.
एआईडीएल और एचआईडीएल के बीच के मुख्य अंतर देखें:
- आम तौर पर, AIDL के पहले से मौजूद
Status
और अपवादों का इस्तेमाल करने से इंटरफ़ेस बेहतर होता है. साथ ही, इंटरफ़ेस के हिसाब से किसी दूसरे स्टेटस टाइप की ज़रूरत नहीं पड़ती. - मेथड में एआईडीएल इंटरफ़ेस के आर्ग्युमेंट, डिफ़ॉल्ट रूप से
@nullable
नहीं होते, जैसे कि वे एचआईडीएल में होते थे.
- आम तौर पर, AIDL के पहले से मौजूद
एआईडीएल एचएएल के लिए SEPolicy
वेंडर कोड को दिखने वाली एआईडीएल सेवा के टाइप में,
hal_service_type
एट्रिब्यूट होना चाहिए. अगर ऐसा नहीं है, तो sepolicy कॉन्फ़िगरेशन, किसी भी अन्य AIDL सेवा के जैसा ही होता है. हालांकि, एचएएल के लिए खास एट्रिब्यूट होते हैं. यहां HAL सेवा के संदर्भ की परिभाषा का एक उदाहरण दिया गया है:
type hal_foo_service, service_manager_type, hal_service_type;
प्लैटफ़ॉर्म की ओर से तय की गई ज़्यादातर सेवाओं के लिए, सही टाइप वाला सेवा कॉन्टेक्स्ट पहले से ही जोड़ दिया जाता है. उदाहरण के लिए, android.hardware.foo.IFoo/default
को पहले से ही hal_foo_service
के तौर पर मार्क किया गया है. हालांकि, अगर कोई फ़्रेमवर्क क्लाइंट कई इंस्टेंस के नामों के साथ काम करता है, तो डिवाइस के हिसाब से service_contexts
फ़ाइलों में अतिरिक्त इंस्टेंस के नाम जोड़ने होंगे:
android.hardware.foo.IFoo/custom_instance u:object_r:hal_foo_service:s0
नया टाइप का एचएएल बनाते समय, आपको एचएएल एट्रिब्यूट जोड़ने होंगे. कोई खास एचएएल एट्रिब्यूट, कई तरह की सेवाओं से जुड़ा हो सकता है. जैसा कि हमने अभी बताया है कि हर सेवा के कई इंस्टेंस हो सकते हैं. एचएएल, foo
के लिए, hal_attribute(foo)
है. यह मैक्रो, hal_foo_client
और
hal_foo_server
एट्रिब्यूट की जानकारी देता है. किसी डोमेन के लिए, hal_client_domain
और
hal_server_domain
मैक्रो, डोमेन को किसी दिए गए एचएएल एट्रिब्यूट से जोड़ते हैं. उदाहरण के लिए, सिस्टम सर्वर इस एचएएल का क्लाइंट है, जो नीति hal_client_domain(system_server, hal_foo)
के मुताबिक है. इसी तरह, HAL सर्वर में hal_server_domain(my_hal_domain, hal_foo)
शामिल होता है.
आम तौर पर, किसी दिए गए एचएएल एट्रिब्यूट के लिए, रेफ़रंस या उदाहरण के तौर पर एचएएल के लिए hal_foo_default
जैसा डोमेन भी बनाएं. हालांकि, कुछ डिवाइस अपने सर्वर के लिए इन डोमेन का इस्तेमाल करते हैं. एक से ज़्यादा सर्वर के लिए डोमेन के बीच अंतर करना सिर्फ़ तब ज़रूरी होता है, जब एक ही इंटरफ़ेस को दिखाने वाले एक से ज़्यादा सर्वर हों और उन्हें लागू करने के लिए अलग-अलग अनुमति सेट की ज़रूरत हो.
इन सभी मैक्रो में, hal_foo
कोई sepolicy ऑब्जेक्ट नहीं है. इसके बजाय, इन मैक्रो में इस टोकन का इस्तेमाल, क्लाइंट सर्वर पेयर से जुड़े एट्रिब्यूट के ग्रुप को रेफ़र करने के लिए किया जाता है.
हालांकि, अब तक hal_foo_service
और hal_foo
(hal_attribute(foo)
से एट्रिब्यूट पेयर) को जोड़ा नहीं गया है. एचएएल एट्रिब्यूट, hal_attribute_service
मैक्रो का इस्तेमाल करने वाली एआईडीएल एचएएल सेवाओं से जुड़ा होता है. एचआईडीएल एचएएल, hal_attribute_hwservice
मैक्रो का इस्तेमाल करते हैं. उदाहरण के लिए, hal_attribute_service(hal_foo, hal_foo_service)
. इसका मतलब है कि hal_foo_client
प्रोसेस, HAL को ऐक्सेस कर सकती हैं और hal_foo_server
प्रोसेस, HAL को रजिस्टर कर सकती हैं. रजिस्ट्रेशन से जुड़े इन नियमों को लागू करने का काम, कॉन्टेक्स्ट मैनेजर (servicemanager
) करता है.
ऐसा हो सकता है कि सेवा के नाम, हमेशा एचएएल एट्रिब्यूट से मेल न खाएं. उदाहरण के लिए,
hal_attribute_service(hal_foo, hal_foo2_service)
. आम तौर पर, इससे पता चलता है कि सेवाओं का इस्तेमाल हमेशा एक साथ किया जाता है. इसलिए, hal_foo2_service
को हटाया जा सकता है और सेवा के सभी कॉन्टेक्स्ट के लिए hal_foo_service
का इस्तेमाल किया जा सकता है. जब एचएएल एक से ज़्यादा hal_attribute_service
इंस्टेंस सेट करते हैं, तो ऐसा इसलिए होता है, क्योंकि एचएएल एट्रिब्यूट का मूल नाम ज़रूरत के मुताबिक नहीं होता और उसे बदला नहीं जा सकता.
इन सभी को एक साथ जोड़ने पर, एचएएल का उदाहरण कुछ ऐसा दिखता है:
public/attributes:
// define hal_foo, hal_foo_client, hal_foo_server
hal_attribute(foo)
public/service.te
// define hal_foo_service
type hal_foo_service, hal_service_type, protected_service, service_manager_type
public/hal_foo.te:
// allow binder connection from client to server
binder_call(hal_foo_client, hal_foo_server)
// allow client to find the service, allow server to register the service
hal_attribute_service(hal_foo, hal_foo_service)
// allow binder communication from server to service_manager
binder_use(hal_foo_server)
private/service_contexts:
// bind an AIDL service name to the selinux type
android.hardware.foo.IFooXxxx/default u:object_r:hal_foo_service:s0
private/<some_domain>.te:
// let this domain use the hal service
binder_use(some_domain)
hal_client_domain(some_domain, hal_foo)
vendor/<some_hal_server_domain>.te
// let this domain serve the hal service
hal_server_domain(some_hal_server_domain, hal_foo)
अटैच किए गए एक्सटेंशन इंटरफ़ेस
एक्सटेंशन को किसी भी बाइंडर इंटरफ़ेस से अटैच किया जा सकता है. भले ही, वह सीधे सेवा मैनेजर के साथ रजिस्टर किया गया टॉप-लेवल इंटरफ़ेस हो या सब-इंटरफ़ेस. एक्सटेंशन लेते समय, आपको यह पुष्टि करनी होगी कि एक्सटेंशन का टाइप सही है. एक्सटेंशन सिर्फ़ उस प्रोसेस से सेट किए जा सकते हैं जो बाइंडर दिखाती है.
जब भी कोई एक्सटेंशन, किसी मौजूदा एचएएल की सुविधा में बदलाव करता है, तो अटैच किए गए एक्सटेंशन का इस्तेमाल करें. जब पूरी तरह से नई सुविधा की ज़रूरत होती है, तो इस तरीके का इस्तेमाल करना ज़रूरी नहीं होता. इसके बजाय, सीधे सेवा मैनेजर के साथ एक्सटेंशन इंटरफ़ेस को रजिस्टर किया जा सकता है. अटैच किए गए एक्सटेंशन इंटरफ़ेस, सबसे ज़्यादा तब काम के होते हैं, जब वे सब-इंटरफ़ेस से अटैच किए जाते हैं. ऐसा इसलिए, क्योंकि ये हैरारकी डीप या मल्टी-इंस्टेंस हो सकती हैं. किसी दूसरी सेवा के बाइंडर इंटरफ़ेस की हैरारकी को मिरर करने के लिए, ग्लोबल एक्सटेंशन का इस्तेमाल करना ज़रूरी है. इसके लिए, सीधे तौर पर अटैच किए गए एक्सटेंशन को मिलती-जुलती सुविधाएं देने के लिए, ज़्यादा बुककीपिंग की ज़रूरत होती है.
बाइंडर पर एक्सटेंशन सेट करने के लिए, इन एपीआई का इस्तेमाल करें:
- NDK बैकएंड:
AIBinder_setExtension
- Java बैकएंड:
android.os.Binder.setExtension
- सीपीपी बैकएंड:
android::Binder::setExtension
- Rust बैकएंड:
binder::Binder::set_extension
बाइंडर के लिए एक्सटेंशन पाने के लिए, इन एपीआई का इस्तेमाल करें:
- NDK बैकएंड:
AIBinder_getExtension
- Java बैकएंड:
android.os.IBinder.getExtension
- सीपीपी बैकएंड:
android::IBinder::getExtension
- Rust बैकएंड:
binder::Binder::get_extension
इन एपीआई के बारे में ज़्यादा जानकारी पाने के लिए, संबंधित बैकएंड में getExtension
फ़ंक्शन के दस्तावेज़ देखें. एक्सटेंशन इस्तेमाल करने का उदाहरण, hardware/interfaces/tests/extension/vibrator
में दिया गया है.
एआईडीएल और एचआईडीएल के बीच के मुख्य अंतर
एआईडीएल एचएएल या एआईडीएल एचएएल इंटरफ़ेस का इस्तेमाल करते समय, एचआईडीएल एचएएल लिखने के मुकाबले अंतरों के बारे में पता होना चाहिए.
- AIDL भाषा का सिंटैक्स, Java से मिलता-जुलता है. HIDL सिंटैक्स, C++ जैसा ही है.
- सभी एआईडीएल इंटरफ़ेस में, गड़बड़ी की स्थिति पहले से मौजूद होती है. कस्टम स्थिति टाइप बनाने के बजाय, इंटरफ़ेस फ़ाइलों में स्थिर स्थिति वाले इंट बनाएं. साथ ही, सीपीपी और एनडीके बैकएंड में
EX_SERVICE_SPECIFIC
और Java बैकएंड मेंServiceSpecificException
का इस्तेमाल करें. गड़बड़ी को मैनेज करना देखें. - बाइंडर ऑब्जेक्ट भेजे जाने पर, AIDL अपने-आप थ्रेड पूल शुरू नहीं करता. आपको उन्हें मैन्युअल तरीके से शुरू करना होगा. इसके लिए, थ्रेड मैनेजमेंट देखें.
- AIDL, ट्रांसपोर्ट से जुड़ी ऐसी गड़बड़ियों पर प्रोसेस को बंद नहीं करता जिनकी पुष्टि नहीं की गई है. हालांकि, HIDL
Return
ऐसी गड़बड़ियों पर प्रोसेस को बंद कर देता है. - AIDL, हर फ़ाइल के लिए सिर्फ़ एक टाइप का एलान कर सकता है.
- आउटपुट पैरामीटर के अलावा, एआईडीएल आर्ग्युमेंट को
in
,out
याinout
के तौर पर तय किया जा सकता है. इसमें सिंक्रोनस कॉलबैक नहीं होते. - AIDL,
handle
के बजायfd
को प्राइमटिव टाइप के तौर पर इस्तेमाल करता है. - HIDL, काम न करने वाले बदलावों के लिए बड़े वर्शन और काम करने वाले बदलावों के लिए छोटे वर्शन का इस्तेमाल करता है. AIDL में, पुराने सिस्टम के साथ काम करने वाले बदलाव किए जाते हैं.
AIDL में, मुख्य वर्शन का कोई खास कॉन्सेप्ट नहीं है. इसके बजाय, इसे पैकेज के नामों में शामिल किया जाता है. उदाहरण के लिए, AIDL, पैकेज के नाम
bluetooth2
का इस्तेमाल कर सकता है. - AIDL, डिफ़ॉल्ट रूप से रीयल टाइम प्राथमिकता को इनहेरिट नहीं करता. रीयल-टाइम में प्राथमिकता के इनहेरिटेंस की सुविधा चालू करने के लिए, हर बाइंडर के लिए
setInheritRt
फ़ंक्शन का इस्तेमाल करना ज़रूरी है.
एचएएल के लिए Vendor Test Suite (VTS) के टेस्ट
Android, एचएएल के लागू होने की पुष्टि करने के लिए, Vendor Test Suite (VTS) पर निर्भर करता है. वीटीएस से यह पक्का करने में मदद मिलती है कि Android, वेंडर के पुराने वर्शन के साथ काम कर सकता है. जिन ऐप्लिकेशन को VTS की जांच में पास नहीं किया गया है उनमें, साथ काम करने से जुड़ी ऐसी समस्याएं मौजूद हैं जिनकी वजह से वे ओएस के आने वाले वर्शन के साथ काम नहीं कर सकते.
एचएएल के लिए, वीटीएस के दो मुख्य हिस्से होते हैं.
1. पुष्टि करें कि डिवाइस पर मौजूद एचएएल, Android के लिए सही और काम के हैं
जांच का यह सेट, test/vts-testcase/hal/treble/vintf
में देखा जा सकता है.
इन टेस्ट से इन चीज़ों की पुष्टि की जाती है:
- VINTF मेनिफ़ेस्ट में बताए गए हर
@VintfStability
इंटरफ़ेस को, रिलीज़ किए गए किसी वर्शन पर फ़्रीज़ कर दिया जाता है. इससे यह पक्का होता है कि इंटरफ़ेस के दोनों पक्ष, इंटरफ़ेस के उस वर्शन की सटीक परिभाषा पर सहमत हैं. यह बुनियादी काम करने के लिए ज़रूरी है. - VINTF मेनिफ़ेस्ट में बताए गए सभी एचएएल, उस डिवाइस पर उपलब्ध होते हैं. एलान की गई एचएएल सेवा का इस्तेमाल करने के लिए ज़रूरी अनुमतियां रखने वाला कोई भी क्लाइंट, उन सेवाओं को किसी भी समय ऐक्सेस और इस्तेमाल कर सकता है.
- VINTF मेनिफ़ेस्ट में बताए गए सभी एचएएल, इंटरफ़ेस का वही वर्शन दिखा रहे हैं जिसे वे मेनिफ़ेस्ट में बताते हैं.
- डिवाइस पर, इस्तेमाल नहीं किए जा सकने वाले एचएएल नहीं दिखाए जा रहे हैं. Android, एचएएल इंटरफ़ेस के पुराने वर्शन के लिए सहायता बंद कर देता है. इस बारे में FCM लाइफ़साइकल में बताया गया है.
- डिवाइस पर ज़रूरी एचएएल मौजूद हैं. Android के ठीक से काम करने के लिए, कुछ एचएएल ज़रूरी हैं.
2. हर एचएएल के काम करने के तरीके की पुष्टि करना
हर HAL इंटरफ़ेस के लिए, VTS की अलग-अलग जांच की जाती है. इससे, यह पुष्टि की जाती है कि क्लाइंट के व्यवहार के बारे में क्या उम्मीद की जा सकती है. टेस्ट केस, एलान किए गए HAL इंटरफ़ेस के हर इंस्टेंस के लिए चलते हैं. साथ ही, लागू किए गए इंटरफ़ेस के वर्शन के आधार पर, खास व्यवहार लागू करते हैं.
इन टेस्ट में, एचएएल लागू करने के हर उस पहलू को शामिल करने की कोशिश की जाती है जिस पर Android फ़्रेमवर्क निर्भर करता है या भविष्य में निर्भर कर सकता है.
इन टेस्ट में, सुविधाओं के काम करने की पुष्टि करना, गड़बड़ी को मैनेज करना, और सेवा से जुड़ा ऐसा कोई भी व्यवहार शामिल है जिसकी उम्मीद क्लाइंट को हो सकती है.
एचएएल डेवलपमेंट के लिए, वीटीएस के माइलस्टोन
Android के HAL इंटरफ़ेस बनाते या उनमें बदलाव करते समय, यह ज़रूरी है कि वीटीएस टेस्ट अप-टू-डेट हों.
Android वेंडर एपीआई रिलीज़ के लिए फ़्रीज़ किए जाने से पहले, वीटीएस टेस्ट पूरे होने चाहिए और वेंडर के लागू किए गए वर्शन की पुष्टि के लिए तैयार होने चाहिए. इंटरफ़ेस फ़्रीज़ होने से पहले, ये तैयार होने चाहिए, ताकि डेवलपर उन्हें लागू कर सकें, उनकी पुष्टि कर सकें, और एचएएल इंटरफ़ेस डेवलपर को सुझाव/राय दे सकें.
Cuttlefish पर VTS
जब हार्डवेयर उपलब्ध नहीं होता, तब Android, एचएएल इंटरफ़ेस के लिए डेवलपमेंट वाहन के तौर पर Cuttlefish का इस्तेमाल करता है. इससे, स्केलेबल VTS और Android के इंटिग्रेशन टेस्टिंग की सुविधा मिलती है.
hal_implementation_test
यह जांच करता है कि Cuttlefish में एचएएल इंटरफ़ेस के नए वर्शन लागू किए गए हैं या नहीं. इससे यह पक्का किया जा सकता है कि Android, नए इंटरफ़ेस को मैनेज करने के लिए तैयार है. साथ ही, नए हार्डवेयर और डिवाइस उपलब्ध होने पर, VTS टेस्ट, नए वेंडर के लागू किए गए वर्शन की जांच करने के लिए तैयार हैं.