एआईडीएल ऐसे एनोटेशन के साथ काम करता है जो एआईडीएल कंपाइलर को एनोटेट किए गए एलिमेंट के बारे में ज़्यादा जानकारी देते हैं. इससे जनरेट किए गए स्टब कोड पर भी असर पड़ता है.
सिंटैक्स, Java के समान है:
@AnnotationName(argument1=value, argument2=value) AidlEntity
यहां, एनोटेशन का नाम AnnotationName
है और AidlEntity
, interface Foo
, void method()
या int arg
जैसी एआईडीएल इकाई है. एक
नोटेशन उस इकाई के साथ जुड़ा होता है जो उसे फ़ॉलो करती है.
कुछ एनोटेशन में, ब्रैकेट के अंदर आर्ग्युमेंट सेट किए जा सकते हैं. जैसा कि ऊपर दिखाया गया है. जिन एनोटेशन में कोई तर्क नहीं होता उन्हें ब्रैकेट की ज़रूरत नहीं होती है. उदाहरण के लिए:
@AnnotationName AidlEntity
ये एनोटेशन Java एनोटेशन के समान नहीं हैं, फिर भी वे बहुत मिलते-जुलते दिखते हैं. उपयोगकर्ता, पसंद के मुताबिक बनाए गए एआईडीएल एनोटेशन नहीं बना सकते. ये सभी एनोटेशन पहले से तय होते हैं. कुछ एनोटेशन सिर्फ़ एक बैकएंड पर असर डालते हैं. ये अन्य बैकएंड में काम नहीं करते. इन पर अलग-अलग पाबंदियां होती हैं, जहां इन्हें अटैच किया जा सकता है.
पहले से तय किए गए एआईडीएल एनोटेशन की सूची यहां दी गई है:
एनोटेशन | Android वर्शन में जोड़ा गया |
---|---|
nullable |
7 |
utf8InCpp |
7 |
VintfStability |
11 |
UnsupportedAppUsage |
10 |
Hide |
11 |
Backing |
11 |
NdkOnlyStableParcelable |
14 |
JavaOnlyStableParcelable |
11 |
JavaDerive |
12 |
JavaPassthrough |
12 |
FixedSize |
12 |
Descriptor |
12 |
अमान्य
nullable
बताता है कि हो सकता है कि एनोटेट की गई इकाई की वैल्यू न दी गई हो.
इस जानकारी को सिर्फ़ तरीके लौटाने के तरीकों, तरीके के पैरामीटर, और पार्स किए जा सकने वाले फ़ील्ड में अटैच किया जा सकता है.
interface IFoo {
// method return types
@nullable Data method();
// method parameters
void method2(in @nullable Data d);
}
parcelable Data {
// parcelable fields
@nullable Data d;
}
एनोटेशन को प्रिमिटिव टाइप के साथ नहीं जोड़ा जा सकता. यह एक गड़बड़ी है.
void method(in @nullable int a); // int is a primitive type
यह जानकारी Java बैकएंड के लिए काम नहीं करती. इसकी वजह यह है कि Java में, सभी नॉन-प्रिमिटिव टाइप रेफ़रंस के ज़रिए पास किए जाते हैं, जो null
हो सकते हैं.
सीपीपी बैकएंड में, @nullable T
, Android 11 या इससे पहले के वर्शन में std::unique_ptr<T>
को मैप करता है. साथ ही, Android 12 या उसके बाद के वर्शन में std::optional<T>
को मैप करता है.
एनडीके बैकएंड में, @nullable T
हमेशा std::optional<T>
को मैप करता है.
T[]
या List<T>
जैसी सूची जैसे टाइप L
के लिए, @nullable L
को std::optional<std::vector<std::optional<T>>>
पर मैप करें (या Android 11 या इससे पहले के वर्शन के लिए, सीपीपी बैकएंड के मामले में std::unique_ptr<std::vector<std::unique_ptr<T>>>
).
इस मैपिंग के लिए एक अपवाद है. जब T
, IBinder
या AIDL इंटरफ़ेस हो, तो @nullable
नो-ऑप होता है. दूसरे शब्दों में, @nullable IBinder
और IBinder
, दोनों android::sp<IBinder>
से बराबर मैप होते हैं, जो पहले से शून्य हो सकता है, क्योंकि यह एक मज़बूत पॉइंटर है (सीपीपी से पता चलता है कि वैल्यू शून्य है, लेकिन टाइप अब भी android::sp<IBinder>
है).
Android 13 और इसके बाद के वर्शन में, पार्स किए जा सकने वाले फ़ील्ड के लिए @nullable(heap=true)
का इस्तेमाल किया जा सकता है. इससे, रिकर्सिव टाइप के मॉडल बनाए जा सकते हैं. @nullable(heap=true)
का इस्तेमाल, तरीके के पैरामीटर या रिटर्न टाइप के साथ नहीं किया जा सकता. जब इसके साथ एनोटेट किया जाता है, तो फ़ील्ड को सीपीपी/एनडीके बैकएंड में, हीप-आवंटित रेफ़रंस std::unique_ptr<T>
के साथ मैप किया जाता है. Java बैकएंड में, @nullable(heap=true)
काम नहीं करता है.
utf8InCpp
utf8InCpp
बताता है कि सीपीपी बैकएंड के लिए, String
को UTF8 फ़ॉर्मैट में दिखाया जाता है. जैसा कि इसके नाम से पता चलता है कि यह एनोटेशन दूसरे बैकएंड के लिए काम नहीं करता.
खास तौर पर, Java बैकएंड में String
हमेशा UTF16 और NDK बैकएंड में UTF8 होता है.
इस जानकारी को उन जगहों पर भी अटैच किया जा सकता है जहां String
टाइप का इस्तेमाल किया जा सकता है. इनमें रिटर्न वैल्यू, पैरामीटर, कॉन्सटैंट जानकारी, और पार्स किए जा सकने वाले फ़ील्ड शामिल हैं.
सीपीपी बैकएंड के लिए, एआईडीएल मैप में @utf8InCpp String
, std::string
के लिए है, जबकि
String
बिना एनोटेशन वाले android::String16
के लिए मैप किया गया है, जहां UTF16 का इस्तेमाल किया जाता है.
ध्यान दें कि utf8InCpp
एनोटेशन के मौजूद होने से, वायर पर स्ट्रिंग को ट्रांसमिट करने का तरीका नहीं बदलता है. स्ट्रिंग हमेशा UTF16 के तौर पर ट्रांसमिट की जाती हैं. utf8InCpp
एनोटेट की गई स्ट्रिंग को ट्रांसमिट करने से पहले, उसे UTF16 में बदला जाता है. जब कोई स्ट्रिंग मिलती है, तो उसे UTF16 से UTF8 में बदल दिया जाता है. ऐसा तब होता है, जब उसके बारे में utf8InCpp
के तौर पर जानकारी दी गई हो.
विंटएफ़स्टेबिलिटी
VintfStability
बताता है कि उपयोगकर्ता की ओर से तय किए गए टाइप (इंटरफ़ेस, पार्सल, और enum) को सिस्टम और वेंडर डोमेन में इस्तेमाल किया जा सकता है. सिस्टम-वेंडर इंटरऑपरेबिलिटी के बारे में ज़्यादा जानने के लिए, एचएएल के लिए एआईडीएल देखें.
एनोटेशन से टाइप के सिग्नेचर में कोई बदलाव नहीं होता. हालांकि, इसे सेट करने पर, टाइप के इंस्टेंस को स्टेबल के तौर पर मार्क किया जाता है, ताकि वह वेंडर और सिस्टम की प्रोसेस के बीच आगे बढ़ सके.
एनोटेशन को सिर्फ़ उपयोगकर्ता की ओर से तय किए गए टाइप की जानकारी के साथ अटैच किया जा सकता है, जैसा कि यहां दिखाया गया है:
@VintfStability
interface IFoo {
....
}
@VintfStability
parcelable Data {
....
}
@VintfStability
enum Type {
....
}
जब किसी टाइप के बारे में VintfStability
के साथ जानकारी दी जाती है, तो टाइप में रेफ़र किए गए किसी अन्य टाइप की भी व्याख्या की जानी चाहिए. इस उदाहरण में, Data
और IBar
दोनों को VintfStability
की मदद से एनोटेट किया जाना चाहिए.
@VintfStability
interface IFoo {
void doSomething(in IBar b); // references IBar
void doAnother(in Data d); // references Data
}
@VintfStability // required
interface IBar {...}
@VintfStability // required
parcelable Data {...}
इसके अलावा, VintfStability
के साथ एनोटेट किए गए टाइप की जानकारी देने वाली एआईडीएल फ़ाइलें सिर्फ़ aidl_interface
सूंग मॉड्यूल टाइप का इस्तेमाल करके बनाई जा सकती हैं. इन फ़ाइलों में stability
प्रॉपर्टी "vintf"
पर सेट होती है.
aidl_interface {
name: "my_interface",
srcs: [...],
stability: "vintf",
}
इस्तेमाल नहीं किया जा सकने वाला ऐप्लिकेशन
UnsupportedAppUsage
व्याख्या से पता चलता है कि व्याख्या किया गया एआईडीएल टाइप,
SDK टूल के अलावा किसी ऐसे इंटरफ़ेस का हिस्सा है जिसे लेगसी ऐप्लिकेशन से ऐक्सेस किया जा सकता है.
छिपे हुए एपीआई के बारे में ज़्यादा जानकारी के लिए, बिना SDK टूल वाले इंटरफ़ेस पर पाबंदियां देखें.
UnsupportedAppUsage
एनोटेशन से, जनरेट किए गए कोड के काम करने के तरीके पर कोई असर नहीं पड़ता. यह एनोटेशन, जनरेट की गई Java क्लास के साथ सिर्फ़ उसी नाम की
Java एनोटेशन के बारे में बताता है.
// in AIDL
@UnsupportedAppUsage
interface IFoo {...}
// in Java
@android.compat.annotation.UnsupportedAppUsage
public interface IFoo {...}
यह गैर-Java बैकएंड के लिए काम नहीं करता.
बैकिंग
Backing
एनोटेशन से यह पता चलता है कि एआईडीएल एनम टाइप का स्टोरेज टाइप क्या है.
@Backing(type="int")
enum Color { RED, BLUE, }
CPP बैकएंड में, इससे int32_t
टाइप की C++ enum क्लास निकलती है.
enum class Color : int32_t {
RED = 0,
BLUE = 1,
}
अगर जानकारी नहीं दी जाती है, तो type
को byte
माना जाता है. यह सीपीपी बैकएंड के लिए, int8_t
से मैप होता है.
type
आर्ग्युमेंट को सिर्फ़ इन इंटिग्रल टाइप पर सेट किया जा सकता है:
byte
(8-बिट चौड़ा)int
(32-बिट चौड़ा)long
(64-बिट चौड़ा)
NdkOnlyStableParcelable
NdkOnlyStableParcelable
, पार्स किए जा सकने वाले डिक्लेरेशन (परिभाषा नहीं है) को स्टेबल के तौर पर मार्क करता है, ताकि उसे अन्य स्थायी AIDL टाइप से रेफ़रंस किया जा सके. यह
JavaOnlyStableParcelable
की तरह है, लेकिन
NdkOnlyStableParcelable
पार्स किए जा सकने वाले एलान को Java के बजाय एनडीके बैकएंड के लिए स्टेबल के तौर पर मार्क करता है.
पार्स किए जा सकने वाले इस टूल का इस्तेमाल करने के लिए:
- आपको
ndk_header
तय करना होगा. - आपके पास पार्सल करने लायक जानकारी देने वाली एक NDK लाइब्रेरी होनी चाहिए. साथ ही, लाइब्रेरी को लाइब्रेरी में कंपाइल किया जाना चाहिए. उदाहरण के लिए,
cc_*
मॉड्यूल पर कोर बिल्ड सिस्टम में,static_libs
याshared_libs
का इस्तेमाल करें.aidl_interface
के लिए,Android.bp
मेंadditional_shared_libraries
से जुड़ी लाइब्रेरी जोड़ें.
JavaOnlyStableParcelable
JavaOnlyStableParcelable
, पार्स किए जा सकने वाले डिक्लेरेशन (परिभाषा नहीं है) को स्टेबल के तौर पर मार्क करता है, ताकि उसे अन्य स्थायी AIDL टाइप से रेफ़रंस किया जा सके.
स्थिर एआईडीएल का इस्तेमाल करने के लिए ज़रूरी है कि उपयोगकर्ता के तय किए गए सभी टाइप स्टेबल हों. पार्सल किए जा सकने वाले प्रॉडक्ट के स्थायी होने के लिए ज़रूरी है कि एआईडीएल सोर्स फ़ाइल में इसके फ़ील्ड के बारे में साफ़ तौर पर जानकारी दी गई हो.
parcelable Data { // Data is a structured parcelable.
int x;
int y;
}
parcelable AnotherData { // AnotherData is also a structured parcelable
Data d; // OK, because Data is a structured parcelable
}
अगर पार्स किए जा सकने वाले एट्रिब्यूट को स्ट्रक्चर नहीं किया गया है या सिर्फ़ एलान किया गया है, तो इसका रेफ़रंस नहीं दिया जा सकता.
parcelable Data; // Data is NOT a structured parcelable
parcelable AnotherData {
Data d; // Error
}
जब पार्स किया जा सकने वाला आपका रेफ़रंस, Android SDK के हिस्से के तौर पर पहले से ही सुरक्षित रूप से उपलब्ध हो, तो JavaOnlyStableParcelable
की मदद से जांच को बदला जा सकता है.
@JavaOnlyStableParcelable
parcelable Data;
parcelable AnotherData {
Data d; // OK
}
JavaDerive
JavaDerive
, Java बैकएंड में पार्स किए जा सकने वाले टाइप के लिए, अपने-आप तरीके जनरेट करता है.
@JavaDerive(equals = true, toString = true)
parcelable Data {
int number;
String str;
}
यह कंट्रोल करने के लिए कि क्या जनरेट करना है, एनोटेशन को अतिरिक्त पैरामीटर की ज़रूरत होती है. इस्तेमाल किए जा सकने वाले पैरामीटर ये हैं:
equals=true
,equals
औरhashCode
तरीके जनरेट करता है.toString=true
,toString
तरीका जनरेट करता है. यह तरीका और फ़ील्ड के नाम प्रिंट करता है. उदाहरण के लिए:Data{number: 42, str: foo}
Javaडिफ़ॉल्ट
Android 13 में जोड़ी गई JavaDefault
से यह कंट्रोल किया जाता है कि
setDefaultImpl
के लिए, डिफ़ॉल्ट रूप से वर्शन लागू करने की सुविधा जनरेट होगी या नहीं. जगह बचाने के लिए, यह सहायता अब डिफ़ॉल्ट रूप से जनरेट नहीं होती.
Javaपासथ्रू
JavaPassthrough
की मदद से, जनरेट किए गए Java API को आर्बिट्रेरी Java एनोटेशन के साथ एनोटेट करने की सुविधा मिलती है.
एआईडीएल में ये एनोटेशन
@JavaPassthrough(annotation="@android.annotation.Alice")
@JavaPassthrough(annotation="@com.android.Alice(arg=com.android.Alice.Value.A)")
बन जाएं
@android.annotation.Alice
@com.android.Alice(arg=com.android.Alice.Value.A)
में बदल सकते हैं.
annotation
पैरामीटर की वैल्यू सीधे तौर पर जनरेट होती है. एआईडीएल कंपाइलर पैरामीटर की वैल्यू पर ध्यान नहीं देता. अगर Java-लेवल पर सिंटैक्स की कोई गड़बड़ी होती है, तो उसे AIDL कंपाइलर नहीं देख पाएगा, बल्कि
Java कंपाइलर उसे देख पाएगा.
यह जानकारी किसी भी एआईडीएल इकाई के साथ अटैच की जा सकती है. यह एनोटेशन उन बैकएंड के लिए काम नहीं करता जो Java के बैकएंड के साथ काम नहीं करते.
तय साइज़
FixedSize
स्ट्रक्चर्ड पार्सल को तय साइज़ के तौर पर मार्क करता है. मार्क होने के बाद, पार्स किए जा सकने वाले फ़ील्ड में नए फ़ील्ड नहीं जोड़े जा सकेंगे. पार्स किए जा सकने वाले सभी फ़ील्ड
का साइज़ भी तय होना चाहिए. इनमें प्रिमिटिव टाइप, ईनम, तय साइज़ के अरे, और FixedSize
से मार्क किए गए दूसरे पार्सलेबल शामिल हैं.
इससे, अलग-अलग कट के लिए कोई गारंटी नहीं मिलती है. साथ ही, मिले-जुले बिटनेस के लिए इस पर भरोसा नहीं किया जाना चाहिए.
जानकारी
Descriptor
ज़बरदस्ती किसी इंटरफ़ेस का इंटरफ़ेस डिस्क्रिप्टर तय करता है.
package android.foo;
@Descriptor(value="android.bar.IWorld")
interface IHello {...}
इस इंटरफ़ेस का डिस्क्रिप्टर android.bar.IWorld
है. अगर
Descriptor
एनोटेशन मौजूद नहीं है, तो डिस्क्रिप्टर
android.foo.IHello
होगा.
यह पहले से पब्लिश किए गए इंटरफ़ेस का नाम बदलने के लिए सही है. नाम बदलने से पहले, बदले गए नाम वाले इंटरफ़ेस के ब्यौरे को इंटरफ़ेस के डिस्क्रिप्टर जैसा ही बनाएं. इससे दोनों इंटरफ़ेस एक-दूसरे से बात कर सकेंगे.
@टिप्पणियों में छिपाएं
एआईडीएल कंपाइलर टिप्पणियों में @hide
की पहचान करता है और मेटलावा को पिकअप करने के लिए इसे Java आउटपुट के ज़रिए पास करता है. इस टिप्पणी से पक्का होता है कि Android के बिल्ड सिस्टम को यह पता हो कि AIDL एपीआई, SDK API नहीं हैं.
टिप्पणियों में @अब काम नहीं करेगा
एआईडीएल कंपाइलर टिप्पणियों में @deprecated
की पहचान एक टैग के तौर पर करता है, ताकि एआईडीएल इकाई की पहचान की जा सके कि अब इसका इस्तेमाल नहीं किया जाना चाहिए.
interface IFoo {
/** @deprecated use bar() instead */
void foo();
void bar();
}
हर बैकएंड में, काम नहीं करने वाली इकाइयों को बैकएंड से जुड़ी जानकारी या एट्रिब्यूट के साथ मार्क किया जाता है.
इससे क्लाइंट कोड को काम न करने वाली इकाइयों के बारे में पता चलने पर चेतावनी मिलती है. उदाहरण के लिए, @Deprecated
एनोटेशन और @deprecated
टैग, Java से जनरेट किए गए कोड से अटैच होते हैं.