एचएएल के लिए एआईडीएल

Android 11 Android में HALs के लिए AIDL का उपयोग करने की क्षमता का परिचय देता है। यह HIDL के बिना Android के कुछ हिस्सों को लागू करना संभव बनाता है। ट्रांज़िशन एचएएल जहां संभव हो विशेष रूप से एआईडीएल का उपयोग करें (जब अपस्ट्रीम एचएएल एचआईडीएल का उपयोग करते हैं, तो एचआईडीएल का उपयोग किया जाना चाहिए)।

फ्रेमवर्क घटकों, जैसे कि system.img में, और हार्डवेयर घटकों, जैसे कि वेंडर.img में, के बीच संवाद करने के लिए AIDL का उपयोग करने वाले vendor.img को स्थिर AIDL का उपयोग करना चाहिए। हालाँकि, एक विभाजन के भीतर संवाद करने के लिए, उदाहरण के लिए एक HAL से दूसरे में, उपयोग करने के लिए IPC तंत्र पर कोई प्रतिबंध नहीं है।

प्रेरणा

एआईडीएल एचआईडीएल की तुलना में लगभग लंबा रहा है, और इसका उपयोग कई अन्य स्थानों पर किया जाता है, जैसे एंड्रॉइड फ्रेमवर्क घटकों या ऐप्स में। अब जब AIDL के पास स्थिरता समर्थन है, तो एक IPC रनटाइम के साथ पूरे स्टैक को लागू करना संभव है। एआईडीएल के पास एचआईडीएल की तुलना में बेहतर वर्जनिंग सिस्टम भी है।

  • एकल IPC भाषा का उपयोग करने का अर्थ है सीखने, डिबग, अनुकूलन और सुरक्षित करने के लिए केवल एक चीज़ होना।
  • एआईडीएल एक इंटरफेस के मालिकों के लिए इन-प्लेस वर्जनिंग का समर्थन करता है:
    • स्वामी इंटरफ़ेस के अंत में या पार्सल योग्य फ़ील्ड में विधियाँ जोड़ सकते हैं। इसका मतलब है कि वर्षों में संस्करण कोड करना आसान है, और साल दर साल लागत भी कम है (प्रकारों को जगह में संशोधित किया जा सकता है और प्रत्येक इंटरफ़ेस संस्करण के लिए अतिरिक्त पुस्तकालयों की कोई आवश्यकता नहीं है)।
    • एक्सटेंशन इंटरफेस को टाइप सिस्टम के बजाय रनटाइम पर जोड़ा जा सकता है, इसलिए इंटरफेस के नए संस्करणों पर डाउनस्ट्रीम एक्सटेंशन को रीबेस करने की कोई जरूरत नहीं है।
  • एक मौजूदा एआईडीएल इंटरफ़ेस का उपयोग सीधे तब किया जा सकता है जब उसका मालिक इसे स्थिर करना चुनता है। इससे पहले, HIDL में इंटरफ़ेस की एक पूरी कॉपी बनानी होगी।

एआईडीएल एचएएल इंटरफ़ेस लिखना

एआईडीएल इंटरफेस के लिए सिस्टम और विक्रेता के बीच उपयोग करने के लिए, इंटरफेस को दो बदलावों की आवश्यकता है:

  • प्रत्येक प्रकार की परिभाषा को @VintfStability के साथ एनोटेट किया जाना चाहिए।
  • aidl_interface घोषणा में stability: "vintf", .

केवल एक इंटरफ़ेस का स्वामी ही ये परिवर्तन कर सकता है।

जब आप ये परिवर्तन करते हैं, तो कार्य करने के लिए इंटरफ़ेस VINTF मेनिफेस्ट में होना चाहिए। वीटीएस परीक्षण vts_treble_vintf_vendor_test का उपयोग करके इसका परीक्षण करें (और संबंधित आवश्यकताएं, जैसे कि जारी किए गए इंटरफेस को रोक दिया गया है)। आप NDK बैकएंड में AIBinder_forceDowngradeToLocalStability , C++ बैकएंड में android::Stability::forceDowngradeToLocalStability , या भेजने से पहले बाइंडर ऑब्जेक्ट पर android.os.Binder#forceDowngradeToSystemStability को कॉल करके इन आवश्यकताओं के बिना @VintfStability इंटरफ़ेस का उपयोग कर सकते हैं। दूसरी प्रक्रिया के लिए। विक्रेता स्थिरता के लिए सेवा को डाउनग्रेड करना जावा में समर्थित नहीं है क्योंकि सभी ऐप सिस्टम के संदर्भ में चलते हैं।

इसके अतिरिक्त, अधिकतम कोड पोर्टेबिलिटी के लिए और अनावश्यक अतिरिक्त लाइब्रेरी जैसी संभावित समस्याओं से बचने के लिए, CPP बैकएंड को अक्षम करें।

ध्यान दें कि नीचे दिए गए कोड उदाहरण में backends का उपयोग सही है, क्योंकि तीन बैकएंड (जावा, एनडीके और सीपीपी) हैं। नीचे दिया गया कोड बताता है कि इसे अक्षम करने के लिए विशेष रूप से CPP बैकएंड का चयन कैसे करें।

    aidl_interface: {
        ...
        backends: {
            cpp: {
                enabled: false,
            },
        },
    }

एआईडीएल एचएएल इंटरफेस ढूँढना

एचएएल के लिए एओएसपी स्थिर एआईडीएल इंटरफेस एचआईडीएल इंटरफेस के समान मूल निर्देशिका में हैं, aidl फोल्डर में।

  • हार्डवेयर/इंटरफेस
  • ढांचे/हार्डवेयर/इंटरफेस
  • सिस्टम/हार्डवेयर/इंटरफेस

आपको vendor या hardware में अन्य hardware/interfaces उपनिर्देशिकाओं में एक्सटेंशन इंटरफेस डालना चाहिए।

एक्सटेंशन इंटरफेस

Android के पास प्रत्येक रिलीज़ के साथ आधिकारिक AOSP इंटरफ़ेस का एक सेट होता है। जब एंड्रॉइड पार्टनर इन इंटरफेस में कार्यक्षमता जोड़ना चाहते हैं, तो उन्हें इन्हें सीधे नहीं बदलना चाहिए क्योंकि इसका मतलब यह होगा कि उनका एंड्रॉइड रनटाइम एओएसपी एंड्रॉइड रनटाइम के साथ असंगत है। जीएमएस उपकरणों के लिए, इन इंटरफेस को बदलने से बचना भी सुनिश्चित करता है कि जीएसआई छवि काम करना जारी रख सकती है।

एक्सटेंशन दो अलग-अलग तरीकों से पंजीकृत हो सकते हैं:

हालाँकि एक विस्तार पंजीकृत है, जब विक्रेता-विशिष्ट (अर्थात अपस्ट्रीम AOSP का हिस्सा नहीं) घटक इंटरफ़ेस का उपयोग करते हैं, तो मर्ज विरोध की कोई संभावना नहीं है। हालाँकि, जब अपस्ट्रीम AOSP घटकों में डाउनस्ट्रीम संशोधन किए जाते हैं, तो मर्ज विरोध हो सकता है, और निम्नलिखित रणनीतियों की सिफारिश की जाती है:

  • अगली रिलीज में इंटरफेस के अतिरिक्त एओएसपी को अपस्ट्रीम किया जा सकता है
  • इंटरफ़ेस परिवर्धन जो आगे लचीलेपन की अनुमति देता है, मर्ज विरोध के बिना, अगली रिलीज में अपस्ट्रीम किया जा सकता है

एक्सटेंशन पार्सल: पार्सलेबल होल्डर

ParcelableHolder एक Parcelable है जिसमें एक और Parcelable हो सकता है। ParcelableHolder का मुख्य उपयोग एक Parcelable एक्स्टेंसिबल बनाना है। उदाहरण के लिए, छवि जो डिवाइस कार्यान्वयनकर्ता AOSP-परिभाषित Parcelable , AospDefinedParcelable को विस्तारित करने में सक्षम होने की अपेक्षा करते हैं, ताकि उनकी मूल्य-वर्धित सुविधाओं को शामिल किया जा सके।

पहले ParcelableHolder के बिना, डिवाइस कार्यान्वयनकर्ता AOSP-परिभाषित स्थिर AIDL इंटरफ़ेस को संशोधित नहीं कर सकते थे क्योंकि यह अधिक फ़ील्ड जोड़ने में त्रुटि होगी:

parcelable AospDefinedParcelable {
  int a;
  String b;
  String x; // ERROR: added by a device implementer
  int[] y; // added by a device implementer
}

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

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>();

एआईडीएल रनटाइम के खिलाफ बिल्डिंग

एआईडीएल के तीन अलग-अलग बैकएंड हैं: जावा, एनडीके, सीपीपी। स्थिर एआईडीएल का उपयोग करने के लिए, आपको हमेशा libbinder की सिस्टम कॉपी को system/lib*/libbinder.so पर उपयोग करना चाहिए और /dev/binder binder पर बात करनी चाहिए। विक्रेता छवि पर कोड के लिए, इसका मतलब है कि libbinder (वीएनडीके से) का उपयोग नहीं किया जा सकता है: इस पुस्तकालय में एक अस्थिर सी ++ एपीआई और अस्थिर आंतरिक है। इसके बजाय, देशी विक्रेता कोड को एआईडीएल के एनडीके बैकएंड का उपयोग करना चाहिए, libbinder_ndk के खिलाफ लिंक (जो सिस्टम libbinder.so द्वारा समर्थित है), और -ndk_platform पुस्तकालयों के खिलाफ लिंक जो कि aidl_interface प्रविष्टियों द्वारा बनाई गई है।

एआईडीएल एचएएल सर्वर उदाहरण के नाम

परंपरा के अनुसार, एआईडीएल एचएएल सेवाओं के पास $package.$type/$instance प्रारूप का एक उदाहरण नाम है। उदाहरण के लिए, वाइब्रेटर एचएएल का एक उदाहरण android.hardware.vibrator.IVibrator/default के रूप में पंजीकृत है।

एआईडीएल एचएएल सर्वर लिखना

@VintfStability सर्वर को वीआईएनटीएफ मेनिफेस्ट में घोषित किया जाना चाहिए, उदाहरण के लिए:

    <hal format="aidl">
        <name>android.hardware.vibrator</name>
        <version>1</version>
        <fqname>IVibrator/default</fqname>
    </hal>

अन्यथा, उन्हें सामान्य रूप से एआईडीएल सेवा पंजीकृत करनी चाहिए। वीटीएस परीक्षण चलाते समय, यह उम्मीद की जाती है कि सभी घोषित एआईडीएल एचएएल उपलब्ध हों।

एआईडीएल क्लाइंट लिखना

एआईडीएल ग्राहकों को खुद को संगतता मैट्रिक्स में घोषित करना चाहिए, उदाहरण के लिए:

    <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 फ़ाइलें बनाएँ
  • नए बनाए गए एआईडीएल पैकेज के लिए बिल्ड नियम बनाएं, जिसमें सभी बैकएंड सक्षम हों
  • एचआईडीएल प्रकारों से एआईडीएल प्रकारों में अनुवाद करने के लिए जावा, सीपीपी, और एनडीके बैकएंड में अनुवाद विधियां बनाएं
  • आवश्यक निर्भरताओं वाली अनुवाद लाइब्रेरी के लिए बिल्ड नियम बनाएं
  • यह सुनिश्चित करने के लिए स्थिर अभिकथन बनाएँ कि HIDL और AIDL प्रगणकों के CPP और NDK बैकएंड में समान मान हों

.hal फ़ाइलों के पैकेज को .aidl फ़ाइलों में बदलने के लिए इन चरणों का पालन करें:

  1. system/tools/hidl/hidl2aidl में स्थित टूल बनाएं।

    इस उपकरण को नवीनतम स्रोत से बनाना सबसे संपूर्ण अनुभव प्रदान करता है। आप पिछले रिलीज से पुरानी शाखाओं पर इंटरफेस को बदलने के लिए नवीनतम संस्करण का उपयोग कर सकते हैं।

    m hidl2aidl
    
  2. कनवर्ट किए जाने वाले पैकेज के बाद आउटपुट डायरेक्टरी के साथ टूल को निष्पादित करें।

    वैकल्पिक रूप से, सभी जेनरेट की गई फ़ाइलों के शीर्ष पर एक नई लाइसेंस फ़ाइल की सामग्री जोड़ने के लिए -l तर्क का उपयोग करें। सही लाइसेंस और दिनांक का उपयोग करना सुनिश्चित करें।

    hidl2aidl -o <output directory> -l <file with license> <package>
    

    उदाहरण के लिए:

    hidl2aidl -o . -l my_license.txt android.hardware.nfc@1.2
    
  3. जनरेट की गई फ़ाइलों को पढ़ें और रूपांतरण के साथ किसी भी समस्या को ठीक करें।

    • conversion.log में पहले ठीक करने के लिए कोई भी हैंडल न की गई समस्याएँ हैं।
    • उत्पन्न .aidl फ़ाइलों में चेतावनियाँ और सुझाव हो सकते हैं जिन पर कार्रवाई की आवश्यकता हो सकती है। ये टिप्पणियाँ // से शुरू होती हैं।
    • पैकेज को साफ करने और उसमें सुधार करने का अवसर लें।
    • उन विशेषताओं के लिए @JavaDerive एनोटेशन की जाँच करें जिनकी आवश्यकता हो सकती है, जैसे toString या equals
  4. केवल उन्हीं लक्ष्यों का निर्माण करें जिनकी आपको आवश्यकता है।

    • बैकएंड अक्षम करें जिनका उपयोग नहीं किया जाएगा। सीपीपी बैकएंड पर एनडीके बैकएंड को प्राथमिकता दें, रनटाइम चुनना देखें।
    • अनुवाद लाइब्रेरी या उनके किसी भी जनरेट किए गए कोड को हटा दें जिसका उपयोग नहीं किया जाएगा।
  5. प्रमुख एआईडीएल/एचआईडीएल अंतर देखें।

    • एआईडीएल की अंतर्निहित Status और अपवादों का उपयोग आम तौर पर इंटरफ़ेस में सुधार करता है और अन्य इंटरफ़ेस-विशिष्ट स्थिति प्रकार की आवश्यकता को हटा देता है।
    • विधियों में एआईडीएल इंटरफ़ेस तर्क डिफ़ॉल्ट रूप से @nullable नहीं हैं जैसे वे एचआईडीएल में थे।

एआईडीएल एचएएल के लिए सिपाही नीति

विक्रेता कोड को दिखाई देने वाली एआईडीएल सेवा प्रकार में hal_service_type विशेषता होनी चाहिए। अन्यथा, सेपोलिसी कॉन्फ़िगरेशन किसी भी अन्य एआईडीएल सेवा के समान है (हालांकि एचएएल के लिए विशेष विशेषताएं हैं)। यहाँ एक एचएएल सेवा संदर्भ की एक उदाहरण परिभाषा दी गई है:

    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 एट्रिब्यूट से संबद्ध करते हैं। उदाहरण के लिए, इस एचएएल का क्लाइंट होने के नाते सिस्टम सर्वर पॉलिसी hal_client_domain(system_server, hal_foo) से मेल खाता है। इसी तरह एक एचएएल सर्वर में hal_server_domain(my_hal_domain, hal_foo) शामिल होता है। आमतौर पर, किसी दिए गए एचएएल विशेषता के लिए, हम संदर्भ या उदाहरण एचएएल के लिए hal_foo_default जैसा डोमेन भी बनाते हैं। हालाँकि, कुछ डिवाइस इन डोमेन का उपयोग अपने स्वयं के सर्वर के लिए करते हैं। कई सर्वरों के लिए डोमेन के बीच अंतर करना केवल तभी मायने रखता है जब हमारे पास एक से अधिक सर्वर हों जो एक ही इंटरफ़ेस की सेवा करते हैं और उनके कार्यान्वयन में एक अलग अनुमति सेट की आवश्यकता होती है। इन सभी मैक्रोज़ में, hal_foo वास्तव में एक सेपोलिसी ऑब्जेक्ट नहीं है। इसके बजाय, इस टोकन का उपयोग इन मैक्रोज़ द्वारा क्लाइंट सर्वर जोड़ी से जुड़े गुणों के समूह को संदर्भित करने के लिए किया जाता है।

हालाँकि, अब तक, हमने hal_foo_service और hal_foo ( hal_attribute(foo) से विशेषता जोड़ी) को संबद्ध नहीं किया है। एक HAL विशेषता hal_attribute_service मैक्रो (HIDL HALs hal_attribute_hwservice मैक्रो का उपयोग करती है) का उपयोग करके AIDL HAL सेवाओं से संबद्ध है। उदाहरण के लिए, hal_attribute_service(hal_foo, hal_foo_service) । इसका अर्थ है कि hal_foo_client प्रक्रियाएँ HAL को प्राप्त कर सकती हैं, और hal_foo_server प्रक्रियाएँ HAL को पंजीकृत कर सकती हैं। इन पंजीकरण नियमों का प्रवर्तन संदर्भ प्रबंधक ( servicemanager प्रबंधक) द्वारा किया जाता है। ध्यान दें, हो सकता है कि सेवा के नाम हमेशा HAL विशेषताओं के अनुरूप न हों। उदाहरण के लिए, हम hal_attribute_service(hal_foo, hal_foo2_service) देख सकते हैं। आम तौर पर, चूंकि इसका तात्पर्य है कि सेवाओं का हमेशा एक साथ उपयोग किया जाता है, हम अपने सभी सेवा संदर्भों के लिए hal_foo_service को हटाने और hal_foo2_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)

संलग्न एक्सटेंशन इंटरफेस

एक एक्सटेंशन किसी भी बाइंडर इंटरफ़ेस से जुड़ा हो सकता है, चाहे वह सेवा प्रबंधक के साथ सीधे पंजीकृत एक शीर्ष-स्तरीय इंटरफ़ेस हो या यह एक उप-इंटरफ़ेस हो। एक्सटेंशन प्राप्त करते समय, आपको यह पुष्टि करनी होगी कि एक्सटेंशन का प्रकार अपेक्षित है। एक्सटेंशन को केवल बाइंडर सर्व करने वाली प्रक्रिया से ही सेट किया जा सकता है।

संलग्न एक्सटेंशन का उपयोग तब किया जाना चाहिए जब कोई एक्सटेंशन किसी मौजूदा एचएएल की कार्यक्षमता को संशोधित करता है। जब पूरी तरह से नई कार्यक्षमता की आवश्यकता होती है, तो इस तंत्र का उपयोग करने की आवश्यकता नहीं होती है, और सीधे सेवा प्रबंधक के साथ एक एक्सटेंशन इंटरफ़ेस पंजीकृत किया जा सकता है। अटैच किए गए एक्सटेंशन इंटरफ़ेस तब सबसे अधिक मायने रखते हैं जब वे उप-इंटरफ़ेस से जुड़े होते हैं, क्योंकि ये पदानुक्रम गहरे या बहु-इंस्टेंस हो सकते हैं। किसी अन्य सेवा के बाइंडर इंटरफ़ेस पदानुक्रम को प्रतिबिंबित करने के लिए वैश्विक एक्सटेंशन का उपयोग करने के लिए व्यापक बहीखाता पद्धति की आवश्यकता होगी ताकि सीधे संलग्न एक्सटेंशन को समान कार्यक्षमता प्रदान की जा सके।

बाइंडर पर एक्सटेंशन सेट करने के लिए, निम्न API का उपयोग करें:

  • NDK बैकएंड में: AIBinder_setExtension
  • जावा बैकएंड में: android.os.Binder.setExtension
  • सीपीपी बैकएंड में: android::Binder::setExtension

बाइंडर पर एक्सटेंशन प्राप्त करने के लिए, निम्न API का उपयोग करें:

  • NDK बैकएंड में: AIBinder_getExtension
  • जावा बैकएंड में: android.os.IBinder.getExtension
  • CPP बैकएंड में: android::IBinder::getExtension

आप इन API के लिए संबंधित बैकएंड में getExtension फ़ंक्शन के दस्तावेज़ीकरण में अधिक जानकारी प्राप्त कर सकते हैं। एक्सटेंशन का उपयोग करने का एक उदाहरण हार्डवेयर/इंटरफेस/परीक्षण/एक्सटेंशन/वाइब्रेटर में पाया जा सकता है।

प्रमुख एआईडीएल/एचआईडीएल अंतर

एआईडीएल एचएएल या एआईडीएल एचएएल इंटरफेस का उपयोग करते समय, एचआईडीएल एचएएल लिखने की तुलना में अंतरों के बारे में जागरूक रहें।

  • एआईडीएल भाषा का सिंटैक्स जावा के करीब है। HIDL सिंटैक्स C++ के समान है।
  • सभी AIDL इंटरफेस में अंतर्निहित त्रुटि स्थितियाँ होती हैं। कस्टम स्थिति प्रकार बनाने के बजाय, इंटरफ़ेस फ़ाइलों में स्थिर स्थिति ints बनाएँ और CPP/NDK बैकएंड में EX_SERVICE_SPECIFIC और Java बैकएंड में ServiceSpecificException का उपयोग करें। एरर हैंडलिंग देखें।
  • बाइंडर ऑब्जेक्ट भेजे जाने पर एआईडीएल स्वचालित रूप से थ्रेडपूल शुरू नहीं करता है। उन्हें मैन्युअल रूप से प्रारंभ किया जाना चाहिए ( थ्रेड प्रबंधन देखें)।
  • एआईडीएल अनियंत्रित परिवहन त्रुटियों पर निरस्त नहीं होता है (एचआईडीएल Return अनियंत्रित त्रुटियों पर निरस्त होता है)।
  • एआईडीएल प्रति फ़ाइल केवल एक प्रकार की घोषणा कर सकता है।
  • एआईडीएल तर्कों को आउटपुट पैरामीटर के अतिरिक्त इन/आउट/इनआउट के रूप में निर्दिष्ट किया जा सकता है (कोई "सिंक्रोनस कॉलबैक नहीं हैं")।
  • एआईडीएल हैंडल के बजाय आदिम प्रकार के रूप में एफडी का उपयोग करता है।
  • HIDL असंगत परिवर्तनों के लिए प्रमुख संस्करणों और संगत परिवर्तनों के लिए लघु संस्करणों का उपयोग करता है। एआईडीएल में, पश्च-संगत परिवर्तन किए जाते हैं। एआईडीएल के पास प्रमुख संस्करणों की कोई स्पष्ट अवधारणा नहीं है; इसके बजाय, इसे पैकेज नामों में शामिल किया गया है। उदाहरण के लिए, एआईडीएल पैकेज नाम bluetooth2 2 का उपयोग कर सकता है।
  • एआईडीएल डिफ़ॉल्ट रूप से रीयलटाइम प्राथमिकता प्राप्त नहीं करता है। रीयलटाइम प्राथमिकता विरासत को सक्षम करने के लिए setInheritRt फ़ंक्शन को प्रति-बाइंडर का उपयोग किया जाना चाहिए।
,

Android 11 Android में HALs के लिए AIDL का उपयोग करने की क्षमता का परिचय देता है। यह HIDL के बिना Android के कुछ हिस्सों को लागू करना संभव बनाता है। ट्रांज़िशन एचएएल जहां संभव हो विशेष रूप से एआईडीएल का उपयोग करें (जब अपस्ट्रीम एचएएल एचआईडीएल का उपयोग करते हैं, तो एचआईडीएल का उपयोग किया जाना चाहिए)।

फ्रेमवर्क घटकों, जैसे कि system.img में, और हार्डवेयर घटकों, जैसे कि वेंडर.img में, के बीच संवाद करने के लिए AIDL का उपयोग करने वाले vendor.img को स्थिर AIDL का उपयोग करना चाहिए। हालाँकि, एक विभाजन के भीतर संवाद करने के लिए, उदाहरण के लिए एक HAL से दूसरे में, उपयोग करने के लिए IPC तंत्र पर कोई प्रतिबंध नहीं है।

प्रेरणा

एआईडीएल एचआईडीएल की तुलना में लगभग लंबा रहा है, और इसका उपयोग कई अन्य स्थानों पर किया जाता है, जैसे एंड्रॉइड फ्रेमवर्क घटकों या ऐप्स में। अब जब AIDL के पास स्थिरता समर्थन है, तो एक IPC रनटाइम के साथ पूरे स्टैक को लागू करना संभव है। एआईडीएल के पास एचआईडीएल की तुलना में बेहतर वर्जनिंग सिस्टम भी है।

  • एकल IPC भाषा का उपयोग करने का अर्थ है सीखने, डिबग, अनुकूलन और सुरक्षित करने के लिए केवल एक चीज़ होना।
  • एआईडीएल एक इंटरफेस के मालिकों के लिए इन-प्लेस वर्जनिंग का समर्थन करता है:
    • स्वामी इंटरफ़ेस के अंत में या पार्सल योग्य फ़ील्ड में विधियाँ जोड़ सकते हैं। इसका मतलब है कि वर्षों में संस्करण कोड करना आसान है, और साल दर साल लागत भी कम है (प्रकारों को जगह में संशोधित किया जा सकता है और प्रत्येक इंटरफ़ेस संस्करण के लिए अतिरिक्त पुस्तकालयों की कोई आवश्यकता नहीं है)।
    • एक्सटेंशन इंटरफेस को टाइप सिस्टम के बजाय रनटाइम पर जोड़ा जा सकता है, इसलिए इंटरफेस के नए संस्करणों पर डाउनस्ट्रीम एक्सटेंशन को रीबेस करने की कोई जरूरत नहीं है।
  • एक मौजूदा एआईडीएल इंटरफ़ेस का उपयोग सीधे तब किया जा सकता है जब उसका मालिक इसे स्थिर करना चुनता है। इससे पहले, HIDL में इंटरफ़ेस की एक पूरी कॉपी बनानी होगी।

एआईडीएल एचएएल इंटरफ़ेस लिखना

एआईडीएल इंटरफेस के लिए सिस्टम और विक्रेता के बीच उपयोग करने के लिए, इंटरफेस को दो बदलावों की आवश्यकता है:

  • प्रत्येक प्रकार की परिभाषा को @VintfStability के साथ एनोटेट किया जाना चाहिए।
  • aidl_interface घोषणा में stability: "vintf", .

केवल एक इंटरफ़ेस का स्वामी ही ये परिवर्तन कर सकता है।

जब आप ये परिवर्तन करते हैं, तो कार्य करने के लिए इंटरफ़ेस VINTF मेनिफेस्ट में होना चाहिए। वीटीएस परीक्षण vts_treble_vintf_vendor_test का उपयोग करके इसका परीक्षण करें (और संबंधित आवश्यकताएं, जैसे कि जारी किए गए इंटरफेस को रोक दिया गया है)। आप NDK बैकएंड में AIBinder_forceDowngradeToLocalStability , C++ बैकएंड में android::Stability::forceDowngradeToLocalStability , या भेजने से पहले बाइंडर ऑब्जेक्ट पर android.os.Binder#forceDowngradeToSystemStability को कॉल करके इन आवश्यकताओं के बिना @VintfStability इंटरफ़ेस का उपयोग कर सकते हैं। दूसरी प्रक्रिया के लिए। विक्रेता स्थिरता के लिए सेवा को डाउनग्रेड करना जावा में समर्थित नहीं है क्योंकि सभी ऐप सिस्टम के संदर्भ में चलते हैं।

इसके अतिरिक्त, अधिकतम कोड पोर्टेबिलिटी के लिए और अनावश्यक अतिरिक्त लाइब्रेरी जैसी संभावित समस्याओं से बचने के लिए, CPP बैकएंड को अक्षम करें।

ध्यान दें कि नीचे दिए गए कोड उदाहरण में backends का उपयोग सही है, क्योंकि तीन बैकएंड (जावा, एनडीके और सीपीपी) हैं। नीचे दिया गया कोड बताता है कि इसे अक्षम करने के लिए विशेष रूप से CPP बैकएंड का चयन कैसे करें।

    aidl_interface: {
        ...
        backends: {
            cpp: {
                enabled: false,
            },
        },
    }

एआईडीएल एचएएल इंटरफेस ढूँढना

एचएएल के लिए एओएसपी स्थिर एआईडीएल इंटरफेस एचआईडीएल इंटरफेस के समान मूल निर्देशिका में हैं, aidl फोल्डर में।

  • हार्डवेयर/इंटरफेस
  • ढांचे/हार्डवेयर/इंटरफेस
  • सिस्टम/हार्डवेयर/इंटरफेस

आपको vendor या hardware में अन्य hardware/interfaces उपनिर्देशिकाओं में एक्सटेंशन इंटरफेस डालना चाहिए।

एक्सटेंशन इंटरफेस

Android के पास प्रत्येक रिलीज़ के साथ आधिकारिक AOSP इंटरफ़ेस का एक सेट होता है। जब एंड्रॉइड पार्टनर इन इंटरफेस में कार्यक्षमता जोड़ना चाहते हैं, तो उन्हें इन्हें सीधे नहीं बदलना चाहिए क्योंकि इसका मतलब यह होगा कि उनका एंड्रॉइड रनटाइम एओएसपी एंड्रॉइड रनटाइम के साथ असंगत है। जीएमएस उपकरणों के लिए, इन इंटरफेस को बदलने से बचना भी सुनिश्चित करता है कि जीएसआई छवि काम करना जारी रख सकती है।

एक्सटेंशन दो अलग-अलग तरीकों से पंजीकृत हो सकते हैं:

हालाँकि एक विस्तार पंजीकृत है, जब विक्रेता-विशिष्ट (अर्थात अपस्ट्रीम AOSP का हिस्सा नहीं) घटक इंटरफ़ेस का उपयोग करते हैं, तो मर्ज विरोध की कोई संभावना नहीं है। हालाँकि, जब अपस्ट्रीम AOSP घटकों में डाउनस्ट्रीम संशोधन किए जाते हैं, तो मर्ज विरोध हो सकता है, और निम्नलिखित रणनीतियों की सिफारिश की जाती है:

  • अगली रिलीज में इंटरफेस के अतिरिक्त एओएसपी को अपस्ट्रीम किया जा सकता है
  • इंटरफ़ेस परिवर्धन जो आगे लचीलेपन की अनुमति देता है, मर्ज विरोध के बिना, अगली रिलीज में अपस्ट्रीम किया जा सकता है

एक्सटेंशन पार्सल: पार्सलेबल होल्डर

ParcelableHolder एक Parcelable है जिसमें एक और Parcelable हो सकता है। ParcelableHolder का मुख्य उपयोग एक Parcelable एक्स्टेंसिबल बनाना है। उदाहरण के लिए, छवि जो डिवाइस कार्यान्वयनकर्ता AOSP-परिभाषित Parcelable , AospDefinedParcelable को विस्तारित करने में सक्षम होने की अपेक्षा करते हैं, ताकि उनकी मूल्य-वर्धित सुविधाओं को शामिल किया जा सके।

पहले ParcelableHolder के बिना, डिवाइस कार्यान्वयनकर्ता AOSP-परिभाषित स्थिर AIDL इंटरफ़ेस को संशोधित नहीं कर सकते थे क्योंकि यह अधिक फ़ील्ड जोड़ने में त्रुटि होगी:

parcelable AospDefinedParcelable {
  int a;
  String b;
  String x; // ERROR: added by a device implementer
  int[] y; // added by a device implementer
}

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

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>();

एआईडीएल रनटाइम के खिलाफ बिल्डिंग

एआईडीएल के तीन अलग-अलग बैकएंड हैं: जावा, एनडीके, सीपीपी। स्थिर एआईडीएल का उपयोग करने के लिए, आपको हमेशा libbinder की सिस्टम कॉपी को system/lib*/libbinder.so पर उपयोग करना चाहिए और /dev/binder binder पर बात करनी चाहिए। विक्रेता छवि पर कोड के लिए, इसका मतलब है कि libbinder (वीएनडीके से) का उपयोग नहीं किया जा सकता है: इस पुस्तकालय में एक अस्थिर सी ++ एपीआई और अस्थिर आंतरिक है। इसके बजाय, देशी विक्रेता कोड को एआईडीएल के एनडीके बैकएंड का उपयोग करना चाहिए, libbinder_ndk के खिलाफ लिंक (जो सिस्टम libbinder.so द्वारा समर्थित है), और -ndk_platform पुस्तकालयों के खिलाफ लिंक जो कि aidl_interface प्रविष्टियों द्वारा बनाई गई है।

एआईडीएल एचएएल सर्वर उदाहरण के नाम

परंपरा के अनुसार, एआईडीएल एचएएल सेवाओं के पास $package.$type/$instance प्रारूप का एक उदाहरण नाम है। उदाहरण के लिए, वाइब्रेटर एचएएल का एक उदाहरण android.hardware.vibrator.IVibrator/default के रूप में पंजीकृत है।

एआईडीएल एचएएल सर्वर लिखना

@VintfStability सर्वर को वीआईएनटीएफ मेनिफेस्ट में घोषित किया जाना चाहिए, उदाहरण के लिए:

    <hal format="aidl">
        <name>android.hardware.vibrator</name>
        <version>1</version>
        <fqname>IVibrator/default</fqname>
    </hal>

अन्यथा, उन्हें सामान्य रूप से एआईडीएल सेवा पंजीकृत करनी चाहिए। वीटीएस परीक्षण चलाते समय, यह उम्मीद की जाती है कि सभी घोषित एआईडीएल एचएएल उपलब्ध हों।

एआईडीएल क्लाइंट लिखना

एआईडीएल ग्राहकों को खुद को संगतता मैट्रिक्स में घोषित करना चाहिए, उदाहरण के लिए:

    <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 फ़ाइलें बनाएँ
  • नए बनाए गए एआईडीएल पैकेज के लिए बिल्ड नियम बनाएं, जिसमें सभी बैकएंड सक्षम हों
  • एचआईडीएल प्रकारों से एआईडीएल प्रकारों में अनुवाद करने के लिए जावा, सीपीपी, और एनडीके बैकएंड में अनुवाद विधियां बनाएं
  • आवश्यक निर्भरताओं वाली अनुवाद लाइब्रेरी के लिए बिल्ड नियम बनाएं
  • यह सुनिश्चित करने के लिए स्थिर अभिकथन बनाएँ कि HIDL और AIDL प्रगणकों के CPP और NDK बैकएंड में समान मान हों

.hal फ़ाइलों के पैकेज को .aidl फ़ाइलों में बदलने के लिए इन चरणों का पालन करें:

  1. system/tools/hidl/hidl2aidl में स्थित टूल बनाएं।

    इस उपकरण को नवीनतम स्रोत से बनाना सबसे संपूर्ण अनुभव प्रदान करता है। आप पिछले रिलीज से पुरानी शाखाओं पर इंटरफेस को बदलने के लिए नवीनतम संस्करण का उपयोग कर सकते हैं।

    m hidl2aidl
    
  2. कनवर्ट किए जाने वाले पैकेज के बाद आउटपुट डायरेक्टरी के साथ टूल को निष्पादित करें।

    वैकल्पिक रूप से, सभी जेनरेट की गई फ़ाइलों के शीर्ष पर एक नई लाइसेंस फ़ाइल की सामग्री जोड़ने के लिए -l तर्क का उपयोग करें। सही लाइसेंस और दिनांक का उपयोग करना सुनिश्चित करें।

    hidl2aidl -o <output directory> -l <file with license> <package>
    

    उदाहरण के लिए:

    hidl2aidl -o . -l my_license.txt android.hardware.nfc@1.2
    
  3. जनरेट की गई फ़ाइलों को पढ़ें और रूपांतरण के साथ किसी भी समस्या को ठीक करें।

    • conversion.log में पहले ठीक करने के लिए कोई भी हैंडल न की गई समस्याएँ हैं।
    • उत्पन्न .aidl फ़ाइलों में चेतावनियाँ और सुझाव हो सकते हैं जिन पर कार्रवाई की आवश्यकता हो सकती है। ये टिप्पणियाँ // से शुरू होती हैं।
    • पैकेज को साफ करने और उसमें सुधार करने का अवसर लें।
    • उन विशेषताओं के लिए @JavaDerive एनोटेशन की जाँच करें जिनकी आवश्यकता हो सकती है, जैसे toString या equals
  4. केवल उन्हीं लक्ष्यों का निर्माण करें जिनकी आपको आवश्यकता है।

    • बैकएंड अक्षम करें जिनका उपयोग नहीं किया जाएगा। सीपीपी बैकएंड पर एनडीके बैकएंड को प्राथमिकता दें, रनटाइम चुनना देखें।
    • अनुवाद लाइब्रेरी या उनके किसी भी जनरेट किए गए कोड को हटा दें जिसका उपयोग नहीं किया जाएगा।
  5. प्रमुख एआईडीएल/एचआईडीएल अंतर देखें।

    • एआईडीएल की अंतर्निहित Status और अपवादों का उपयोग आम तौर पर इंटरफ़ेस में सुधार करता है और अन्य इंटरफ़ेस-विशिष्ट स्थिति प्रकार की आवश्यकता को हटा देता है।
    • विधियों में एआईडीएल इंटरफ़ेस तर्क डिफ़ॉल्ट रूप से @nullable नहीं हैं जैसे वे एचआईडीएल में थे।

एआईडीएल एचएएल के लिए सिपाही नीति

विक्रेता कोड को दिखाई देने वाली एआईडीएल सेवा प्रकार में hal_service_type विशेषता होनी चाहिए। अन्यथा, सेपोलिसी कॉन्फ़िगरेशन किसी भी अन्य एआईडीएल सेवा के समान है (हालांकि एचएएल के लिए विशेष विशेषताएं हैं)। यहाँ एक एचएएल सेवा संदर्भ की एक उदाहरण परिभाषा दी गई है:

    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 एट्रिब्यूट से संबद्ध करते हैं। उदाहरण के लिए, इस एचएएल का क्लाइंट होने के नाते सिस्टम सर्वर पॉलिसी hal_client_domain(system_server, hal_foo) से मेल खाता है। इसी तरह एक एचएएल सर्वर में hal_server_domain(my_hal_domain, hal_foo) शामिल होता है। आमतौर पर, किसी दिए गए एचएएल विशेषता के लिए, हम संदर्भ या उदाहरण एचएएल के लिए hal_foo_default जैसा डोमेन भी बनाते हैं। हालाँकि, कुछ डिवाइस इन डोमेन का उपयोग अपने स्वयं के सर्वर के लिए करते हैं। कई सर्वरों के लिए डोमेन के बीच अंतर करना केवल तभी मायने रखता है जब हमारे पास एक से अधिक सर्वर हों जो एक ही इंटरफ़ेस की सेवा करते हैं और उनके कार्यान्वयन में एक अलग अनुमति सेट की आवश्यकता होती है। इन सभी मैक्रोज़ में, hal_foo वास्तव में एक सेपोलिसी ऑब्जेक्ट नहीं है। इसके बजाय, इस टोकन का उपयोग इन मैक्रोज़ द्वारा क्लाइंट सर्वर जोड़ी से जुड़े गुणों के समूह को संदर्भित करने के लिए किया जाता है।

हालाँकि, अब तक, हमने hal_foo_service और hal_foo ( hal_attribute(foo) से विशेषता जोड़ी) को संबद्ध नहीं किया है। एक HAL विशेषता hal_attribute_service मैक्रो (HIDL HALs hal_attribute_hwservice मैक्रो का उपयोग करती है) का उपयोग करके AIDL HAL सेवाओं से संबद्ध है। उदाहरण के लिए, hal_attribute_service(hal_foo, hal_foo_service) । इसका अर्थ है कि hal_foo_client प्रक्रियाएँ HAL को प्राप्त कर सकती हैं, और hal_foo_server प्रक्रियाएँ HAL को पंजीकृत कर सकती हैं। इन पंजीकरण नियमों का प्रवर्तन संदर्भ प्रबंधक ( servicemanager प्रबंधक) द्वारा किया जाता है। ध्यान दें, हो सकता है कि सेवा के नाम हमेशा HAL विशेषताओं के अनुरूप न हों। उदाहरण के लिए, हम hal_attribute_service(hal_foo, hal_foo2_service) देख सकते हैं। आम तौर पर, चूंकि इसका तात्पर्य है कि सेवाओं का हमेशा एक साथ उपयोग किया जाता है, हम अपने सभी सेवा संदर्भों के लिए hal_foo_service को हटाने और hal_foo2_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)

संलग्न एक्सटेंशन इंटरफेस

एक एक्सटेंशन किसी भी बाइंडर इंटरफ़ेस से जुड़ा हो सकता है, चाहे वह सेवा प्रबंधक के साथ सीधे पंजीकृत एक शीर्ष-स्तरीय इंटरफ़ेस हो या यह एक उप-इंटरफ़ेस हो। एक्सटेंशन प्राप्त करते समय, आपको यह पुष्टि करनी होगी कि एक्सटेंशन का प्रकार अपेक्षित है। एक्सटेंशन को केवल बाइंडर सर्व करने वाली प्रक्रिया से ही सेट किया जा सकता है।

संलग्न एक्सटेंशन का उपयोग तब किया जाना चाहिए जब कोई एक्सटेंशन किसी मौजूदा एचएएल की कार्यक्षमता को संशोधित करता है। जब पूरी तरह से नई कार्यक्षमता की आवश्यकता होती है, तो इस तंत्र का उपयोग करने की आवश्यकता नहीं होती है, और सीधे सेवा प्रबंधक के साथ एक एक्सटेंशन इंटरफ़ेस पंजीकृत किया जा सकता है। अटैच किए गए एक्सटेंशन इंटरफ़ेस तब सबसे अधिक मायने रखते हैं जब वे उप-इंटरफ़ेस से जुड़े होते हैं, क्योंकि ये पदानुक्रम गहरे या बहु-इंस्टेंस हो सकते हैं। किसी अन्य सेवा के बाइंडर इंटरफ़ेस पदानुक्रम को प्रतिबिंबित करने के लिए वैश्विक एक्सटेंशन का उपयोग करने के लिए व्यापक बहीखाता पद्धति की आवश्यकता होगी ताकि सीधे संलग्न एक्सटेंशन को समान कार्यक्षमता प्रदान की जा सके।

बाइंडर पर एक्सटेंशन सेट करने के लिए, निम्न API का उपयोग करें:

  • NDK बैकएंड में: AIBinder_setExtension
  • जावा बैकएंड में: android.os.Binder.setExtension
  • सीपीपी बैकएंड में: android::Binder::setExtension

बाइंडर पर एक्सटेंशन प्राप्त करने के लिए, निम्न API का उपयोग करें:

  • NDK बैकएंड में: AIBinder_getExtension
  • जावा बैकएंड में: android.os.IBinder.getExtension
  • CPP बैकएंड में: android::IBinder::getExtension

आप इन API के लिए संबंधित बैकएंड में getExtension फ़ंक्शन के दस्तावेज़ीकरण में अधिक जानकारी प्राप्त कर सकते हैं। एक्सटेंशन का उपयोग करने का एक उदाहरण हार्डवेयर/इंटरफेस/परीक्षण/एक्सटेंशन/वाइब्रेटर में पाया जा सकता है।

प्रमुख एआईडीएल/एचआईडीएल अंतर

एआईडीएल एचएएल या एआईडीएल एचएएल इंटरफेस का उपयोग करते समय, एचआईडीएल एचएएल लिखने की तुलना में अंतरों के बारे में जागरूक रहें।

  • एआईडीएल भाषा का सिंटैक्स जावा के करीब है। HIDL सिंटैक्स C++ के समान है।
  • सभी AIDL इंटरफेस में अंतर्निहित त्रुटि स्थितियाँ होती हैं। कस्टम स्थिति प्रकार बनाने के बजाय, इंटरफ़ेस फ़ाइलों में स्थिर स्थिति ints बनाएँ और CPP/NDK बैकएंड में EX_SERVICE_SPECIFIC और Java बैकएंड में ServiceSpecificException का उपयोग करें। एरर हैंडलिंग देखें।
  • बाइंडर ऑब्जेक्ट भेजे जाने पर एआईडीएल स्वचालित रूप से थ्रेडपूल शुरू नहीं करता है। उन्हें मैन्युअल रूप से प्रारंभ किया जाना चाहिए ( थ्रेड प्रबंधन देखें)।
  • एआईडीएल अनियंत्रित परिवहन त्रुटियों पर निरस्त नहीं होता है (एचआईडीएल Return अनियंत्रित त्रुटियों पर निरस्त होता है)।
  • एआईडीएल प्रति फ़ाइल केवल एक प्रकार की घोषणा कर सकता है।
  • एआईडीएल तर्कों को आउटपुट पैरामीटर के अतिरिक्त इन/आउट/इनआउट के रूप में निर्दिष्ट किया जा सकता है (कोई "सिंक्रोनस कॉलबैक नहीं हैं")।
  • एआईडीएल हैंडल के बजाय आदिम प्रकार के रूप में एफडी का उपयोग करता है।
  • HIDL असंगत परिवर्तनों के लिए प्रमुख संस्करणों और संगत परिवर्तनों के लिए लघु संस्करणों का उपयोग करता है। एआईडीएल में, पश्च-संगत परिवर्तन किए जाते हैं। एआईडीएल के पास प्रमुख संस्करणों की कोई स्पष्ट अवधारणा नहीं है; इसके बजाय, इसे पैकेज नामों में शामिल किया गया है। उदाहरण के लिए, एआईडीएल पैकेज नाम bluetooth2 2 का उपयोग कर सकता है।
  • एआईडीएल डिफ़ॉल्ट रूप से रीयलटाइम प्राथमिकता प्राप्त नहीं करता है। रीयलटाइम प्राथमिकता विरासत को सक्षम करने के लिए setInheritRt फ़ंक्शन को प्रति-बाइंडर का उपयोग किया जाना चाहिए।