एआईडीएल बैकएंड

संग्रह की मदद से व्यवस्थित रहें अपनी प्राथमिकताओं के आधार पर, कॉन्टेंट को सेव करें और कैटगरी में बांटें.

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

एआईडीएल के निम्नलिखित बैकएंड हैं:

बैकएंड भाषा एपीआई सतह सिस्टम बनाएं
जावा जावा एसडीके/सिस्टमएपी (स्थिर*) सब
एनडीके सी++ libbinder_ndk (स्थिर*) सहायताल_इंटरफ़ेस
सीपीपी सी++ लिबबाइंडर (अस्थिर) सब
जंग जंग libbinder_rs (अस्थिर) सहायताल_इंटरफ़ेस
  • ये API सरफेस स्थिर हैं, लेकिन कई API, जैसे कि सेवा प्रबंधन के लिए, आंतरिक प्लेटफ़ॉर्म उपयोग के लिए आरक्षित हैं और ऐप्स के लिए उपलब्ध नहीं हैं। ऐप्स में AIDL का उपयोग करने के तरीके के बारे में अधिक जानकारी के लिए, डेवलपर दस्तावेज़ देखें।
  • रस्ट बैकएंड को Android 12 में पेश किया गया था; एनडीके बैकएंड एंड्रॉइड 10 के रूप में उपलब्ध है।
  • जंग का टोकरा libbinder_ndk के ऊपर बनाया गया है। एपेक्स बाइंडर क्रेट का उसी तरह उपयोग करते हैं जैसे सिस्टम साइड पर कोई और करता है। जंग के हिस्से को एक एपेक्स में बांधा जाता है और इसके अंदर भेज दिया जाता है। यह सिस्टम विभाजन पर libbinder_ndk.so पर निर्भर करता है।

सिस्टम बनाएं

बैकएंड के आधार पर, AIDL को स्टब कोड में संकलित करने के दो तरीके हैं। बिल्ड सिस्टम के बारे में अधिक जानकारी के लिए, सूंग मॉड्यूल संदर्भ देखें।

कोर बिल्ड सिस्टम

किसी भी cc_ या java_ Android.bp मॉड्यूल (या उनके Android.mk समकक्ष) में, .aidl फ़ाइलों को स्रोत फ़ाइलों के रूप में निर्दिष्ट किया जा सकता है। इस मामले में, एआईडीएल के जावा/सीपीपी बैकएंड का उपयोग किया जाता है (एनडीके बैकएंड नहीं), और संबंधित एआईडीएल फाइलों का उपयोग करने के लिए कक्षाएं स्वचालित रूप से मॉड्यूल में जोड़ दी जाती हैं। local_include_dirs जैसे विकल्प, जो बिल्ड सिस्टम को उस मॉड्यूल में AIDL फ़ाइलों के लिए रूट पथ बताता है, इन मॉड्यूल में एक aidl: समूह के तहत निर्दिष्ट किया जा सकता है। ध्यान दें कि रस्ट बैकएंड केवल रस्ट के साथ उपयोग के लिए है। rust_ मॉड्यूल को अलग तरीके से संभाला जाता है क्योंकि AIDL फाइलें स्रोत फ़ाइलों के रूप में निर्दिष्ट नहीं होती हैं। इसके बजाय, aidl_interface मॉड्यूल <aidl_interface name>-rust नामक एक rustlib उत्पन्न करता है जिसे इसके विरुद्ध जोड़ा जा सकता है। अधिक जानकारी के लिए, जंग एआईडीएल उदाहरण देखें।

सहायताल_इंटरफ़ेस

स्थिर एआईडीएल देखें। इस बिल्ड सिस्टम के साथ उपयोग किए जाने वाले प्रकारों को संरचित किया जाना चाहिए; यानी सीधे एआईडीएल में व्यक्त किया जाता है। इसका मतलब है कि कस्टम पार्सल का उपयोग नहीं किया जा सकता है।

प्रकार

आप aidl संकलक को प्रकारों के संदर्भ कार्यान्वयन के रूप में मान सकते हैं। जब आप एक इंटरफ़ेस बनाते हैं, तो परिणामी इंटरफ़ेस फ़ाइल देखने के लिए aidl --lang=<backend> ... का आह्वान करें। जब आप aidl_interface मॉड्यूल का उपयोग करते हैं, तो आप आउटपुट को out/soong/.intermediates/<path to module>/ में देख सकते हैं।

जावा/एआईडीएल प्रकार सी++ टाइप एनडीके प्रकार जंग प्रकार
बूलियन बूल बूल बूल
बाइट int8_t int8_t i8
चारो char16_t char16_t यू 16
पूर्णांक int32_t int32_t i32
लंबा int64_t int64_t i64
पानी पर तैरना पानी पर तैरना पानी पर तैरना f32
दोहरा दोहरा दोहरा f64
डोरी एंड्रॉइड :: स्ट्रिंग 16 एसटीडी :: स्ट्रिंग डोरी
android.os.Parcelable एंड्रॉइड :: पार्सल करने योग्य एन/ए एन/ए
इबिन्दर android::IBinder ndk::SpAIBinder बाइंडर :: स्पाइबिंदर
टी[] एसटीडी::वेक्टर<टी> एसटीडी::वेक्टर<टी> में: और [टी]
आउट: वीईसी<टी>
बाइट[] एसटीडी::वेक्टर<uint8_t> एसटीडी::वेक्टर<int8_t> 1 में: और [u8]
आउट: वीईसी<u8>
सूची<टी> एसटीडी::वेक्टर<टी> 2 एसटीडी::वेक्टर<टी> 3 में: और [टी] 4
आउट: वीईसी<टी>
फाइल डिस्क्रिप्टर android::आधार::unique_fd एन/ए बाइंडर :: पार्सल :: पार्सलफाइल डिस्क्रिप्टर
पार्सलफाइल डिस्क्रिप्टर android::os::ParcelFileDescriptor ndk::ScopedFileDescriptor बाइंडर :: पार्सल :: पार्सलफाइल डिस्क्रिप्टर
इंटरफ़ेस प्रकार (टी) android::sp<T> एसटीडी::shared_ptr<T> बांधने की मशीन::मजबूत
पार्सल योग्य प्रकार (टी) टी टी टी
संघ प्रकार (टी) 5 टी टी टी
टी [एन] 6 एसटीडी::सरणी<टी, एन> एसटीडी::सरणी<टी, एन> [टी; एन]

1. Android 12 या उच्चतर में, बाइट सरणियाँ संगतता कारणों से int8_t के बजाय uint8_t का उपयोग करती हैं।

2. C++ बैकएंड List<T> का समर्थन करता है जहां T String , IBinder , ParcelFileDescriptor या पार्सल करने योग्य में से एक है। एंड्रॉइड 13 या उच्चतर में, T सरणियों को छोड़कर कोई भी गैर-आदिम प्रकार (इंटरफ़ेस प्रकार सहित) हो सकता है। एओएसपी अनुशंसा करता है कि आप T[] जैसे सरणी प्रकारों का उपयोग करें, क्योंकि वे सभी बैकएंड में काम करते हैं।

3. NDK बैकएंड List<T> का समर्थन करता है जहां T String , ParcelFileDescriptor या पार्सल करने योग्य में से एक है। एंड्रॉइड 13 या उच्चतर में, T सरणियों को छोड़कर कोई भी गैर-आदिम प्रकार हो सकता है।

4. रस्ट कोड के लिए प्रकारों को अलग-अलग तरीके से पारित किया जाता है, यह इस बात पर निर्भर करता है कि वे इनपुट (एक तर्क), या एक आउटपुट (एक लौटा हुआ मूल्य) हैं।

5. यूनियन प्रकार Android 12 और उच्चतर में समर्थित हैं।

6. Android 13 या उच्चतर में, निश्चित आकार के सरणियाँ समर्थित हैं। निश्चित आकार के सरणियों में कई आयाम हो सकते हैं (जैसे int[3][4] )। जावा बैकएंड में, निश्चित आकार के सरणियों को सरणी प्रकारों के रूप में दर्शाया जाता है।

दिशात्मकता (इन/आउट/इनआउट)

फ़ंक्शन के लिए तर्कों के प्रकार निर्दिष्ट करते समय, आप उन्हें in , out , या inout के रूप में निर्दिष्ट कर सकते हैं। यह नियंत्रित करता है कि आईपीसी कॉल के लिए किस दिशा में जानकारी दी जाती है। in डिफ़ॉल्ट दिशा है, और यह इंगित करता है कि कॉलर से कैली तक डेटा पास किया गया है। out का मतलब है कि कॉल करने वाले से कॉल करने वाले को डेटा पास किया जाता है। inout इन दोनों का संयोजन है। हालांकि, Android टीम अनुशंसा करती है कि आप तर्क विनिर्देशक inout का उपयोग करने से बचें। यदि आप संस्करण वाले इंटरफ़ेस और पुराने कैली के साथ inout का उपयोग करते हैं, तो अतिरिक्त फ़ील्ड जो केवल कॉलर में मौजूद हैं, उनके डिफ़ॉल्ट मानों पर रीसेट हो जाते हैं। जंग के संबंध में, एक सामान्य inout प्रकार प्राप्त करता है &mut Vec<T> , और inout प्रकार की एक सूची प्राप्त होती है &mut Vec<T>

UTF8/UTF16

सीपीपी बैकएंड के साथ आप चुन सकते हैं कि स्ट्रिंग्स utf-8 या utf-16 हैं या नहीं। एआईडीएल में स्ट्रिंग्स को @utf8InCpp String के रूप में घोषित करें ताकि उन्हें स्वचालित रूप से utf-8 में परिवर्तित किया जा सके। NDK और रस्ट बैकएंड हमेशा utf-8 स्ट्रिंग्स का उपयोग करते हैं। utf8InCpp एनोटेशन के बारे में अधिक जानकारी के लिए, AIDL में एनोटेशन देखें।

अशक्तता

आप सीपीपी और एनडीके बैकएंड के लिए शून्य मानों को उजागर करने के लिए जावा बैकएंड में @nullable के साथ उन प्रकारों को एनोटेट कर सकते हैं जो शून्य हो सकते हैं। रस्ट बैकएंड में ये @nullable प्रकार Option<T> के रूप में सामने आते हैं। मूल सर्वर डिफ़ॉल्ट रूप से शून्य मानों को अस्वीकार करते हैं। इसका एकमात्र अपवाद interface और IBinder प्रकार हैं, जो NDK पढ़ने और CPP/NDK लिखने के लिए हमेशा शून्य हो सकते हैं। nullable एनोटेशन के बारे में अधिक जानकारी के लिए, AIDL में एनोटेशन देखें।

कस्टम पार्सलेबल

कोर बिल्ड सिस्टम में सी ++ और जावा बैकएंड में, आप एक पार्सलेबल घोषित कर सकते हैं जिसे मैन्युअल रूप से लक्षित बैकएंड (सी ++ या जावा में) में कार्यान्वित किया जाता है।

    package my.package;
    parcelable Foo;

या सी ++ हेडर घोषणा के साथ:

    package my.package;
    parcelable Foo cpp_header "my/package/Foo.h";

फिर आप इस पार्सल को एआईडीएल फाइलों में एक प्रकार के रूप में उपयोग कर सकते हैं, लेकिन यह एआईडीएल द्वारा उत्पन्न नहीं होगा।

जंग कस्टम पार्सलेबल का समर्थन नहीं करता है।

डिफॉल्ट मान

संरचित पार्सलेबल प्राइमेटिव, String एस और इन प्रकार के सरणियों के लिए प्रति-फ़ील्ड डिफ़ॉल्ट मान घोषित कर सकते हैं।

    parcelable Foo {
      int numField = 42;
      String stringField = "string value";
      char charValue = 'a';
      ...
    }

जावा बैकएंड में जब डिफ़ॉल्ट मान गायब होते हैं, तो फ़ील्ड को आदिम प्रकारों के लिए null मान और गैर-आदिम प्रकारों के लिए शून्य के रूप में प्रारंभ किया जाता है।

अन्य बैकएंड में, जब डिफ़ॉल्ट मान परिभाषित नहीं होते हैं, तो फ़ील्ड को डिफ़ॉल्ट आरंभिक मानों के साथ प्रारंभ किया जाता है। उदाहरण के लिए, C++ बैकएंड में, String फ़ील्ड्स को एक खाली स्ट्रिंग के रूप में प्रारंभ किया जाता है और List<T> फ़ील्ड्स को एक खाली vector<T> के रूप में प्रारंभ किया जाता है। @nullable फ़ील्ड को शून्य-मान फ़ील्ड के रूप में प्रारंभ किया गया है।

त्रुटि प्रबंधन

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

त्रुटियों के साथ आउटपुट पैरामीटर

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

किस त्रुटि मान का उपयोग करना है

कई अंतर्निहित त्रुटि मान किसी भी एआईडीएल इंटरफेस में उपयोग किए जा सकते हैं, लेकिन कुछ को एक विशेष तरीके से माना जाता है। उदाहरण के लिए, EX_UNSUPPORTED_OPERATION और EX_ILLEGAL_ARGUMENT त्रुटि स्थिति का वर्णन करते समय उपयोग करने के लिए ठीक हैं, लेकिन EX_TRANSACTION_FAILED का उपयोग नहीं किया जाना चाहिए क्योंकि इसे अंतर्निहित बुनियादी ढांचे द्वारा विशेष माना जाता है। इन अंतर्निहित मूल्यों के बारे में अधिक जानकारी के लिए बैकएंड विशिष्ट परिभाषाओं की जाँच करें।

यदि एआईडीएल इंटरफ़ेस को अतिरिक्त त्रुटि मानों की आवश्यकता होती है जो अंतर्निहित त्रुटि प्रकारों द्वारा कवर नहीं किए जाते हैं, तो वे विशेष सेवा-विशिष्ट अंतर्निहित त्रुटि का उपयोग कर सकते हैं जो उपयोगकर्ता द्वारा परिभाषित सेवा-विशिष्ट त्रुटि मान को शामिल करने की अनुमति देता है। . इन सेवा-विशिष्ट त्रुटियों को आम तौर पर एआईडीएल इंटरफ़ेस में एक const int या int -backed enum के रूप में परिभाषित किया जाता है और बाइंडर द्वारा पार्स नहीं किया जाता है।

जावा में, त्रुटियाँ अपवादों को मैप करती हैं, जैसे android.os.RemoteException । सेवा-विशिष्ट अपवादों के लिए, जावा उपयोगकर्ता द्वारा परिभाषित त्रुटि के साथ android.os.ServiceSpecificException का उपयोग करता है।

Android में मूल कोड अपवादों का उपयोग नहीं करता है। CPP बैकएंड android::binder::Status का उपयोग करता है। एनडीके बैकएंड ndk::ScopedAStatus का उपयोग करता है। एआईडीएल द्वारा उत्पन्न प्रत्येक विधि विधि की स्थिति का प्रतिनिधित्व करते हुए इनमें से एक लौटाती है। रस्ट बैकएंड एनडीके के समान अपवाद कोड मानों का उपयोग करता है, लेकिन उन्हें उपयोगकर्ता को वितरित करने से पहले मूल रस्ट त्रुटियों ( StatusCode , ExceptionCode ) में परिवर्तित करता है। सेवा-विशिष्ट त्रुटियों के लिए, लौटाई गई Status या ScopedAStatus उपयोगकर्ता द्वारा परिभाषित त्रुटि के साथ EX_SERVICE_SPECIFIC का उपयोग करती है।

अंतर्निहित त्रुटि प्रकार निम्न फ़ाइलों में पाए जा सकते हैं:

बैकएंड परिभाषा
जावा android/os/Parcel.java
सीपीपी binder/Status.h
एनडीके android/binder_status.h
जंग android/binder_status.h

विभिन्न बैकएंड का उपयोग करना

ये निर्देश Android प्लेटफ़ॉर्म कोड के लिए विशिष्ट हैं। ये उदाहरण परिभाषित प्रकार, my.package.IFoo का उपयोग करते हैं। रस्ट बैकएंड का उपयोग करने के निर्देशों के लिए, Android रस्ट पैटर्न पृष्ठ पर Rust AIDL उदाहरण देखें।

आयात के प्रकार

चाहे परिभाषित प्रकार एक इंटरफ़ेस, पार्सल योग्य या संघ है, आप इसे जावा में आयात कर सकते हैं:

import my.package.IFoo;

या सीपीपी बैकएंड में:

#include <my/package/IFoo.h>

या aidl बैकएंड में (अतिरिक्त सहायता नामस्थान पर ध्यान दें):

#include <aidl/my/package/IFoo.h>

या रस्ट बैकएंड में:

use my_package::aidl::my::package::IFoo;

यद्यपि आप जावा में नेस्टेड प्रकार आयात कर सकते हैं, सीपीपी/एनडीके बैकएंड में आपको इसके मूल प्रकार के लिए शीर्षलेख शामिल करना होगा। उदाहरण के लिए, my/package/IFoo.aidl ( IFoo फ़ाइल का मूल प्रकार है) में परिभाषित एक नेस्टेड प्रकार Bar आयात करते समय आपको CPP बैकएंड (या <aidl/my/package/IFoo.h> ) के लिए <my/package/IFoo.h> शामिल करना होगा। <aidl/my/package/IFoo.h> बैकएंड के लिए)।

सेवाओं को लागू करना

किसी सेवा को लागू करने के लिए, आपको मूल स्टब वर्ग से इनहेरिट करना होगा। यह वर्ग बाइंडर ड्राइवर से कमांड पढ़ता है और आपके द्वारा लागू की जाने वाली विधियों को निष्पादित करता है। कल्पना कीजिए कि आपके पास एआईडीएल फाइल इस तरह है:

    package my.package;
    interface IFoo {
        int doFoo();
    }

जावा में, आपको इस वर्ग से विस्तार करना होगा:

    import my.package.IFoo;
    public class MyFoo extends IFoo.Stub {
        @Override
        int doFoo() { ... }
    }

सीपीपी बैकएंड में:

    #include <my/package/BnFoo.h>
    class MyFoo : public my::package::BnFoo {
        android::binder::Status doFoo(int32_t* out) override;
    }

aidl बैकएंड में (अतिरिक्त सहायता नामस्थान पर ध्यान दें):

    #include <aidl/my/package/BnFoo.h>
    class MyFoo : public aidl::my::package::BnFoo {
        ndk::ScopedAStatus doFoo(int32_t* out) override;
    }

जंग बैकएंड में:

    use aidl_interface_name::aidl::my::package::IFoo::{BnFoo, IFoo};
    use binder;

    /// This struct is defined to implement IRemoteService AIDL interface.
    pub struct MyFoo;

    impl Interface for MyFoo {}

    impl IFoo for MyFoo {
        fn doFoo(&self) -> binder::Result<()> {
           ...
           Ok(())
        }
    }

पंजीकरण और सेवाएं प्राप्त करना

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

जावा में:

    import android.os.ServiceManager;
    // registering
    ServiceManager.addService("service-name", myService);
    // getting
    myService = IFoo.Stub.asInterface(ServiceManager.getService("service-name"));
    // waiting until service comes up (new in Android 11)
    myService = IFoo.Stub.asInterface(ServiceManager.waitForService("service-name"));
    // waiting for declared (VINTF) service to come up (new in Android 11)
    myService = IFoo.Stub.asInterface(ServiceManager.waitForDeclaredService("service-name"));

सीपीपी बैकएंड में:

    #include <binder/IServiceManager.h>
    // registering
    defaultServiceManager()->addService(String16("service-name"), myService);
    // getting
    status_t err = getService<IFoo>(String16("service-name"), &myService);
    // waiting until service comes up (new in Android 11)
    myService = waitForService<IFoo>(String16("service-name"));
    // waiting for declared (VINTF) service to come up (new in Android 11)
    myService = waitForDeclaredService<IFoo>(String16("service-name"));

aidl बैकएंड में (अतिरिक्त सहायता नामस्थान पर ध्यान दें):

    #include <android/binder_manager.h>
    // registering
    status_t err = AServiceManager_addService(myService->asBinder().get(), "service-name");
    // getting
    myService = IFoo::fromBinder(SpAIBinder(AServiceManager_getService("service-name")));
    // is a service declared in the VINTF manifest
    // VINTF services have the type in the interface instance name.
    bool isDeclared = AServiceManager_isDeclared("android.hardware.light.ILights/default");
    // wait until a service is available (if isDeclared or you know it's available)
    myService = IFoo::fromBinder(SpAIBinder(AServiceManager_waitForService("service-name")));

जंग बैकएंड में:

use myfoo::MyFoo;
use binder;
use aidl_interface_name::aidl::my::package::IFoo::BnFoo;

fn main() {
    binder::ProcessState::start_thread_pool();
    // [...]
    let my_service = MyFoo;
    let my_service_binder = BnFoo::new_binder(
        my_service,
        BinderFeatures::default(),
    );
    binder::add_service("myservice", my_service_binder).expect("Failed to register service?");
    // Does not return - spawn or perform any work you mean to do before this call.
    binder::ProcessState::join_thread_pool()
}

जब बाइंडर की मेजबानी करने वाली सेवा की मृत्यु हो जाती है, तो आप सूचना प्राप्त करने का अनुरोध कर सकते हैं। यह कॉलबैक प्रॉक्सी को लीक होने से बचाने में मदद कर सकता है या त्रुटि पुनर्प्राप्ति में सहायता कर सकता है। इन कॉलों को बाइंडर प्रॉक्सी ऑब्जेक्ट्स पर करें।

  • जावा में, android.os.IBinder::linkToDeath का उपयोग करें।
  • सीपीपी बैकएंड में, android::IBinder::linkToDeath का उपयोग करें।
  • एनडीके बैकएंड में, AIBinder_linkToDeath का उपयोग करें।
  • रस्ट बैकएंड में, एक DeathRecipient ऑब्जेक्ट बनाएं, फिर कॉल करें my_binder.link_to_death(&mut my_death_recipient) । ध्यान दें कि क्योंकि DeathRecipient कॉलबैक का मालिक है, आपको उस वस्तु को तब तक जीवित रखना होगा जब तक आप सूचनाएं प्राप्त करना चाहते हैं।

फोन करने वाले की जानकारी

कर्नेल बाइंडर कॉल प्राप्त करते समय, कॉलर की जानकारी कई एपीआई में उपलब्ध होती है। पीआईडी ​​​​(या प्रोसेस आईडी) उस प्रक्रिया की लिनक्स प्रक्रिया आईडी को संदर्भित करता है जो लेनदेन भेज रही है। यूआईडी (या यूजर आईडी) लिनक्स यूजर आईडी को संदर्भित करता है। एकतरफा कॉल प्राप्त करते समय, कॉलिंग पीआईडी ​​​​0 है। जब एक बाइंडर लेनदेन संदर्भ के बाहर, ये फ़ंक्शन वर्तमान प्रक्रिया के पीआईडी ​​​​और यूआईडी को वापस कर देते हैं।

जावा बैकएंड में:

    ... = Binder.getCallingPid();
    ... = Binder.getCallingUid();

सीपीपी बैकएंड में:

    ... = IPCThreadState::self()->getCallingPid();
    ... = IPCThreadState::self()->getCallingUid();

एनडीके बैकएंड में:

    ... = AIBinder_getCallingPid();
    ... = AIBinder_getCallingUid();

रस्ट बैकएंड में, इंटरफ़ेस को लागू करते समय, निम्नलिखित निर्दिष्ट करें (इसे डिफ़ॉल्ट रूप से अनुमति देने के बजाय):

    ... = ThreadState::get_calling_pid();
    ... = ThreadState::get_calling_uid();

सेवाओं के लिए बग रिपोर्ट और डिबगिंग एपीआई

जब बग्रेपोर्ट चलते हैं (उदाहरण के लिए, adb bugreport के साथ), तो वे विभिन्न मुद्दों को डीबग करने में सहायता के लिए सिस्टम के चारों ओर से जानकारी एकत्र करते हैं। एआईडीएल सेवाओं के लिए, बग्रेपोर्ट सेवा प्रबंधक के साथ पंजीकृत सभी सेवाओं पर अपनी जानकारी को बग्रेपोर्ट में डंप करने के लिए बाइनरी dumpsys का उपयोग करते हैं। आप dumpsys SERVICE [ARGS] से जानकारी प्राप्त करने के लिए कमांडलाइन पर dumpsys का भी उपयोग कर सकते हैं। C++ और Java बैकएंड में, आप उस क्रम को नियंत्रित कर सकते हैं जिसमें सेवाओं को addService के लिए अतिरिक्त तर्कों का उपयोग करके डंप किया जाता है। डिबगिंग के दौरान किसी सेवा का PID प्राप्त करने के लिए आप dumpsys --pid SERVICE का भी उपयोग कर सकते हैं।

अपनी सेवा में कस्टम आउटपुट जोड़ने के लिए, आप अपने सर्वर ऑब्जेक्ट में dump विधि को ओवरराइड कर सकते हैं जैसे आप एआईडीएल फ़ाइल में परिभाषित किसी अन्य आईपीसी विधि को लागू कर रहे हैं। ऐसा करते समय, आपको डंपिंग को ऐप अनुमति android.permission.DUMP तक सीमित रखना चाहिए या डंपिंग को विशिष्ट UIDs तक सीमित करना चाहिए।

जावा बैकएंड में:

    @Override
    protected void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter fout,
        @Nullable String[] args) {...}

सीपीपी बैकएंड में:

    status_t dump(int, const android::android::Vector<android::String16>&) override;

एनडीके बैकएंड में:

    binder_status_t dump(int fd, const char** args, uint32_t numArgs) override;

रस्ट बैकएंड में, इंटरफ़ेस को लागू करते समय, निम्नलिखित निर्दिष्ट करें (इसे डिफ़ॉल्ट रूप से अनुमति देने के बजाय):

    fn dump(&self, mut file: &File, args: &[&CStr]) -> binder::Result<()>

गतिशील रूप से इंटरफ़ेस डिस्क्रिप्टर प्राप्त करना

इंटरफ़ेस डिस्क्रिप्टर इंटरफ़ेस के प्रकार की पहचान करता है। डिबगिंग करते समय या जब आपके पास कोई अज्ञात बाइंडर होता है तो यह उपयोगी होता है।

जावा में, आप कोड के साथ इंटरफ़ेस डिस्क्रिप्टर प्राप्त कर सकते हैं जैसे:

    service = /* get ahold of service object */
    ... = service.asBinder().getInterfaceDescriptor();

सीपीपी बैकएंड में:

    service = /* get ahold of service object */
    ... = IInterface::asBinder(service)->getInterfaceDescriptor();

एनडीके और जंग बैकएंड इस कार्यक्षमता का समर्थन नहीं करते हैं।

स्थिर रूप से इंटरफ़ेस डिस्क्रिप्टर प्राप्त करना

कभी-कभी (जैसे @VintfStability सेवाओं को पंजीकृत करते समय), आपको यह जानना होगा कि इंटरफ़ेस डिस्क्रिप्टर स्थिर रूप से क्या है। जावा में, आप कोड जोड़कर डिस्क्रिप्टर प्राप्त कर सकते हैं जैसे:

    import my.package.IFoo;
    ... IFoo.DESCRIPTOR

सीपीपी बैकएंड में:

    #include <my/package/BnFoo.h>
    ... my::package::BnFoo::descriptor

aidl बैकएंड में (अतिरिक्त सहायता नामस्थान पर ध्यान दें):

    #include <aidl/my/package/BnFoo.h>
    ... aidl::my::package::BnFoo::descriptor

जंग बैकएंड में:

    aidl::my::package::BnFoo::get_descriptor()

एनम रेंज

देशी बैकएंड में, आप उन संभावित मूल्यों पर पुनरावृति कर सकते हैं जो एक एनम ले सकता है। कोड आकार के कारण, यह वर्तमान में जावा में समर्थित नहीं है।

AIDL में परिभाषित एक MyEnum के लिए, पुनरावृत्ति निम्नानुसार प्रदान की जाती है।

सीपीपी बैकएंड में:

    ::android::enum_range<MyEnum>()

एनडीके बैकएंड में:

   ::ndk::enum_range<MyEnum>()

जंग बैकएंड में:

    MyEnum::enum_range()

धागा प्रबंधन

एक प्रक्रिया में libbinder का प्रत्येक उदाहरण एक थ्रेडपूल रखता है। अधिकांश उपयोग के मामलों के लिए, यह बिल्कुल एक थ्रेडपूल होना चाहिए, जो सभी बैकएंड में साझा किया गया हो। इसका एकमात्र अपवाद तब होता है जब विक्रेता कोड /dev/vndbinder से बात करने के लिए libbinder की दूसरी प्रति लोड कर सकता है। चूंकि यह एक अलग बाइंडर नोड पर है, इसलिए थ्रेडपूल साझा नहीं किया जाता है।

जावा बैकएंड के लिए, थ्रेडपूल केवल आकार में बढ़ सकता है (क्योंकि यह पहले ही शुरू हो चुका है):

    BinderInternal.setMaxThreads(<new larger value>);

CPP बैकएंड के लिए, निम्नलिखित ऑपरेशन उपलब्ध हैं:

    // set max threadpool count (default is 15)
    status_t err = ProcessState::self()->setThreadPoolMaxThreadCount(numThreads);
    // create threadpool
    ProcessState::self()->startThreadPool();
    // add current thread to threadpool (adds thread to max thread count)
    IPCThreadState::self()->joinThreadPool();

इसी तरह, एनडीके बैकएंड में:

    bool success = ABinderProcess_setThreadPoolMaxThreadCount(numThreads);
    ABinderProcess_startThreadPool();
    ABinderProcess_joinThreadPool();

जंग बैकएंड में:

    binder::ProcessState::start_thread_pool();
    binder::add_service(“myservice”, my_service_binder).expect(“Failed to register service?”);
    binder::ProcessState::join_thread_pool();

आरक्षित नाम

C++, Java, और Rust कुछ नाम कीवर्ड के रूप में या भाषा-विशिष्ट उपयोग के लिए आरक्षित करते हैं। जबकि एआईडीएल भाषा नियमों के आधार पर प्रतिबंधों को लागू नहीं करता है, आरक्षित नाम से मेल खाने वाले फ़ील्ड या टाइप नामों का उपयोग करने से सी ++ या जावा के लिए संकलन विफलता हो सकती है। रस्ट के लिए, "कच्चे पहचानकर्ता" सिंटैक्स का उपयोग करके फ़ील्ड या प्रकार का नाम बदल दिया जाता है, जिसे r# उपसर्ग का उपयोग करके एक्सेस किया जा सकता है।

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

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

बचने के लिए नाम: * C++ कीवर्ड्स * Java कीवर्ड्स * रस्ट कीवर्ड्स