बाइंडर आईपीसी का उपयोग करना

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

यह पृष्ठ Android 8 में बाइंडर ड्राइवर में परिवर्तन का वर्णन करता है, बाइंडर IPC का उपयोग करने पर विवरण प्रदान करता है, और आवश्यक SELinux नीति सूचीबद्ध करता है।

बाइंडर ड्राइवर में परिवर्तन

एंड्रॉइड 8 से शुरू होकर, एंड्रॉइड फ्रेमवर्क और एचएएल अब बाइंडर का उपयोग करके एक दूसरे के साथ संवाद करते हैं। जैसा कि यह संचार नाटकीय रूप से बाइंडर ट्रैफ़िक को बढ़ाता है, Android 8 में बाइंडर IPC को तेज़ रखने के लिए डिज़ाइन किए गए कई सुधार शामिल हैं। एसओसी विक्रेताओं और ओईएम को एंड्रॉइड-4.4, एंड्रॉइड-4.9, और कर्नेल/सामान्य प्रोजेक्ट की प्रासंगिक शाखाओं से सीधे विलय करना चाहिए।

एकाधिक बाइंडर डोमेन (संदर्भ)

सामान्य-4.4 और उच्चतर, अपस्ट्रीम सहित

फ्रेमवर्क (डिवाइस-इंडिपेंडेंट) और वेंडर (डिवाइस-स्पेसिफिक) कोड के बीच बाइंडर ट्रैफिक को साफ-साफ विभाजित करने के लिए, Android 8 ने बाइंडर कॉन्टेक्स्ट की अवधारणा पेश की। प्रत्येक बाइंडर संदर्भ का अपना डिवाइस नोड और अपना स्वयं का संदर्भ (सेवा) प्रबंधक होता है। आप संदर्भ प्रबंधक को केवल उस डिवाइस नोड के माध्यम से एक्सेस कर सकते हैं जिससे यह संबंधित है और, जब एक निश्चित संदर्भ के माध्यम से एक बाइंडर नोड को पास किया जाता है, तो यह उसी संदर्भ से केवल एक अन्य प्रक्रिया से सुलभ होता है, इस प्रकार डोमेन को एक दूसरे से पूरी तरह से अलग कर देता है। उपयोग करने के विवरण के लिए, vndbinder और vndservicemanager देखें।

बिखराव-इकट्ठा

सामान्य-4.4 और उच्चतर, अपस्ट्रीम सहित

एंड्रॉइड के पिछले रिलीज में, बाइंडर कॉल में डेटा के प्रत्येक टुकड़े को तीन बार कॉपी किया गया था:

  • कॉलिंग प्रक्रिया में इसे एक बार Parcel में क्रमबद्ध करने के लिए
  • एक बार कर्नेल ड्राइवर में Parcel को लक्ष्य प्रक्रिया में कॉपी करने के लिए
  • एक बार टारगेट प्रोसेस में Parcel को अनसीरियलाइज करने के लिए

एंड्रॉइड 8 प्रतियों की संख्या को 3 से 1 तक कम करने के लिए स्कैटर-इकट्ठा अनुकूलन का उपयोग करता है। पहले Parcel में डेटा को क्रमबद्ध करने के बजाय, डेटा अपनी मूल संरचना और मेमोरी लेआउट में रहता है और ड्राइवर तुरंत इसे लक्ष्य प्रक्रिया में कॉपी करता है। डेटा लक्ष्य प्रक्रिया में होने के बाद, संरचना और मेमोरी लेआउट समान होता है और डेटा को दूसरी प्रति की आवश्यकता के बिना पढ़ा जा सकता है।

महीन दाने वाला ताला

सामान्य-4.4 और उच्चतर, अपस्ट्रीम सहित

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

इस समस्या को हल करने के शुरुआती प्रयासों में ग्लोबल लॉक को होल्ड करने के दौरान प्रीमेशन को अक्षम करना शामिल था। हालाँकि, यह एक वास्तविक समाधान की तुलना में एक हैक अधिक था, और अंततः अपस्ट्रीम द्वारा खारिज कर दिया गया और खारिज कर दिया गया। बाद के प्रयासों ने लॉकिंग को और अधिक ठीक-ठाक बनाने पर ध्यान केंद्रित किया, जिसका एक संस्करण जनवरी 2017 से पिक्सेल उपकरणों पर चल रहा है। जबकि उन परिवर्तनों में से अधिकांश को सार्वजनिक किया गया था, बाद के संस्करणों में पर्याप्त सुधार किए गए थे।

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

वास्तविक समय प्राथमिकता विरासत

सामान्य-4.4 और सामान्य-4.9 (अपस्ट्रीम जल्द ही आ रहा है)

बाइंडर ड्राइवर ने हमेशा अच्छी प्राथमिकता वाली विरासत का समर्थन किया है। एंड्रॉइड में प्रक्रियाओं की बढ़ती संख्या वास्तविक समय की प्राथमिकता पर चलती है, कुछ मामलों में अब यह समझ में आता है कि यदि रीयल-टाइम थ्रेड बाइंडर कॉल करता है, तो उस कॉल को संभालने वाली प्रक्रिया में थ्रेड रीयल-टाइम प्राथमिकता पर भी चलता है। . इन उपयोग के मामलों का समर्थन करने के लिए, Android 8 अब बाइंडर ड्राइवर में रीयल-टाइम प्राथमिकता विरासत को लागू करता है।

लेन-देन-स्तरीय प्राथमिकता वंशानुक्रम के अलावा, नोड प्राथमिकता वंशानुक्रम एक नोड (बाइंडर सर्विस ऑब्जेक्ट) को न्यूनतम प्राथमिकता निर्दिष्ट करने की अनुमति देता है, जिस पर इस नोड में कॉल निष्पादित की जानी चाहिए। एंड्रॉइड के पिछले संस्करण पहले से ही अच्छे मूल्यों के साथ नोड प्राथमिकता विरासत का समर्थन करते हैं, लेकिन एंड्रॉइड 8 रीयल-टाइम शेड्यूलिंग नीतियों नोड विरासत के लिए समर्थन जोड़ता है।

उपयोगकर्तास्थान परिवर्तन

एंड्रॉइड 8 में एक अपवाद के साथ सामान्य कर्नेल में वर्तमान बाइंडर ड्राइवर के साथ काम करने के लिए आवश्यक सभी यूजरस्पेस परिवर्तन शामिल हैं: /dev/binder के लिए रीयल-टाइम प्राथमिकता विरासत को अक्षम करने के लिए मूल कार्यान्वयन ने एक ioctl का उपयोग किया। बाद के विकास ने प्राथमिकता वंशानुक्रम के नियंत्रण को एक अधिक सुक्ष्म विधि में बदल दिया जो प्रति बाइंडर मोड (और संदर्भ के अनुसार नहीं) है। इस प्रकार, ioctl एंड्रॉइड कॉमन ब्रांच में नहीं है और इसके बजाय हमारे कॉमन कर्नेल में सबमिट किया गया है

इस परिवर्तन का प्रभाव यह है कि प्रत्येक नोड के लिए डिफ़ॉल्ट रूप से रीयल-टाइम प्राथमिकता वंशानुक्रम अक्षम है। Android प्रदर्शन टीम ने hwbinder डोमेन में सभी नोड्स के लिए रीयल-टाइम प्राथमिकता इनहेरिटेंस को सक्षम करना लाभदायक पाया है। उसी प्रभाव को प्राप्त करने के लिए, इस परिवर्तन को उपयोक्तास्थान में चेरी-चुनें।

सामान्य गुठली के लिए SHAs

बाइंडर ड्राइवर में आवश्यक परिवर्तन प्राप्त करने के लिए, उपयुक्त SHA से सिंक करें:

  • सामान्य-3.18
    cc8b90c121de Android: बाइंडर: पुनर्स्थापित करने पर प्रियो अनुमतियों की जांच न करें।
  • सामान्य-4.4
    76b376eac7a2 Android: बाइंडर: पुनर्स्थापित करने पर प्रियो अनुमतियों की जाँच न करें।
  • सामान्य-4.9
    ecd972d4f9b5 Android: बाइंडर: पुनर्स्थापित करने पर प्रियो अनुमतियों की जांच न करें।

बाइंडर आईपीसी का उपयोग करना

ऐतिहासिक रूप से, विक्रेता प्रक्रियाओं ने संचार करने के लिए बाइंडर इंटरप्रोसेस कम्युनिकेशन (IPC) का उपयोग किया है। Android 8 में, /dev/binder डिवाइस नोड फ्रेमवर्क प्रक्रियाओं के लिए अनन्य हो जाता है, जिसका अर्थ है कि विक्रेता प्रक्रियाओं की अब इस तक पहुंच नहीं है। विक्रेता प्रक्रियाएं /dev/hwbinder तक पहुंच सकती हैं, लेकिन उन्हें HIDL का उपयोग करने के लिए अपने AIDL इंटरफेस को बदलना होगा। विक्रेता जो विक्रेता प्रक्रियाओं के बीच एआईडीएल इंटरफेस का उपयोग करना जारी रखना चाहते हैं, उनके लिए एंड्रॉइड बाइंडर आईपीसी का समर्थन करता है जैसा कि नीचे वर्णित है। एंड्रॉइड 10 में, स्थिर एआईडीएल सभी प्रक्रियाओं को /dev/binder का उपयोग करने की अनुमति देता है जबकि स्थिरता गारंटी के लिए समाधान भी करता है और /dev/hwbinder हल करता है। स्थिर एआईडीएल का उपयोग कैसे करें, एचएएल के लिए एआईडीएल देखें।

vndbinder

एंड्रॉइड 8 विक्रेता सेवाओं द्वारा उपयोग के लिए एक नए बाइंडर डोमेन का समर्थन करता है, जिसे /dev/binder के बजाय /dev/binder /dev/vndbinder का उपयोग करके एक्सेस किया जाता है। /dev/vndbinder के जुड़ने से, Android के पास अब निम्नलिखित तीन IPC डोमेन हैं:

आईपीसी डोमेन विवरण
/dev/binder एआईडीएल इंटरफेस के साथ फ्रेमवर्क/ऐप प्रक्रियाओं के बीच आईपीसी
/dev/hwbinder एचआईडीएल इंटरफेस के साथ ढांचे/विक्रेता प्रक्रियाओं के बीच आईपीसी
एचआईडीएल इंटरफेस के साथ विक्रेता प्रक्रियाओं के बीच आईपीसी
/dev/vndbinder एआईडीएल इंटरफेस के साथ विक्रेता/विक्रेता प्रक्रियाओं के बीच आईपीसी

/dev/vndbinder प्रकट होने के लिए, सुनिश्चित करें कि कर्नेल कॉन्फ़िगरेशन आइटम CONFIG_ANDROID_BINDER_DEVICES "binder,hwbinder,vndbinder" पर सेट है (यह Android के सामान्य कर्नेल ट्री में डिफ़ॉल्ट है)।

आम तौर पर, विक्रेता प्रक्रिया बाइंडर ड्राइवर को सीधे नहीं खोलती है और इसके बजाय libbinder यूजरस्पेस लाइब्रेरी से लिंक करती है, जो बाइंडर ड्राइवर को खोलती है। ::android::ProcessState() के लिए एक विधि जोड़ना libbinder के लिए बाइंडर ड्राइवर का चयन करता है। विक्रेता प्रक्रियाओं को ProcessState, IPCThreadState में कॉल करने से पहले या सामान्य रूप से कोई भी बाइंडर कॉल करने से पहले इस विधि को कॉल करना चाहिए। उपयोग करने के लिए, विक्रेता प्रक्रिया (क्लाइंट और सर्वर) के main() के बाद निम्न कॉल करें:

ProcessState::initWithDriver("/dev/vndbinder");

vndservicemanager

पहले, बाइंडर सेवाओं को servicemanager के साथ पंजीकृत किया गया था, जहां उन्हें अन्य प्रक्रियाओं द्वारा पुनर्प्राप्त किया जा सकता था। Android 8 में, servicemanager का उपयोग अब फ्रेमवर्क और ऐप प्रक्रियाओं द्वारा विशेष रूप से किया जाता है और विक्रेता प्रक्रियाएँ अब इसे एक्सेस नहीं कर सकती हैं।

हालांकि, विक्रेता सेवाएं अब vndservicemanager का उपयोग कर सकती हैं, servicemanager का एक नया उदाहरण जो /dev/vndbinder के बजाय /dev/binder dev/vndbinder का उपयोग करता है और जो समान स्रोतों से फ्रेमवर्क servicemanager के रूप में बनाया गया है। विक्रेता प्रक्रियाओं को vndservicemanager से बात करने के लिए परिवर्तन करने की आवश्यकता नहीं है; जब कोई वेंडर प्रक्रिया खुलती है / dev/vndbinder , तो सर्विस लुकअप स्वचालित रूप से vndservicemanager में चला जाता है।

vndservicemanager बाइनरी Android के डिफ़ॉल्ट डिवाइस मेकफ़ाइल में शामिल है।

सेलिनक्स नीति

वेंडर प्रक्रियाएँ जो एक दूसरे के साथ संवाद करने के लिए बाइंडर कार्यक्षमता का उपयोग करना चाहती हैं, उन्हें निम्नलिखित की आवश्यकता है:

  1. /dev/vndbinder तक पहुंच।
  2. बाइंडर {transfer, call} vndservicemanager में हुक करता है।
  3. किसी भी वेंडर डोमेन ए के लिए binder_call(A, B) जो वेंडर बाइंडर इंटरफेस पर वेंडर डोमेन बी में कॉल करना चाहता है।
  4. vndservicemanager में {add, find} सेवाओं की अनुमति।

आवश्यकताओं 1 और 2 को पूरा करने के लिए, vndbinder_use() मैक्रो का उपयोग करें:

vndbinder_use(some_vendor_process_domain);

आवश्यकता 3 को पूरा करने के लिए, विक्रेता प्रक्रियाओं ए और बी के लिए binder_call(A, B) जिसे बाइंडर पर बात करने की आवश्यकता होती है, और नाम बदलने की आवश्यकता नहीं होती है।

आवश्यकता 4 को पूरा करने के लिए, आपको सेवा के नाम, सेवा लेबल और नियमों को प्रबंधित करने के तरीके में परिवर्तन करना होगा।

SELinux पर विवरण के लिए, Android में सुरक्षा-वर्धित Linux देखें। Android 8.0 में SELinux पर विवरण के लिए, Android 8.0 के लिए SELinux देखें।

सेवा नाम

पहले, विक्रेता पंजीकृत सेवा नामों को एक service_contexts फ़ाइल में संसाधित करता है और उस फ़ाइल तक पहुँचने के लिए संबंधित नियम जोड़ता है। device/google/marlin/sepolicy से उदाहरण service_contexts फ़ाइल :

AtCmdFwd                              u:object_r:atfwd_service:s0
cneservice                            u:object_r:cne_service:s0
qti.ims.connectionmanagerservice      u:object_r:imscm_service:s0
rcs                                   u:object_r:radio_service:s0
uce                                   u:object_r:uce_service:s0
vendor.qcom.PeripheralManager         u:object_r:per_mgr_service:s0

Android 8 में, vndservicemanager इसके बजाय vndservice_contexts फ़ाइल लोड करता है। वेंडर सेवाएँ जो vndservicemanager में माइग्रेट हो रही हैं (और जो पहले से ही पुरानी service_contexts फ़ाइल में हैं) को नई vndservice_contexts फ़ाइल में जोड़ा जाना चाहिए।

सेवा लेबल

पहले, सेवा लेबल जैसे u:object_r:atfwd_service:s0 को service.te फ़ाइल में परिभाषित किया गया था। उदाहरण:

type atfwd_service,      service_manager_type;

एंड्रॉइड 8 में, आपको प्रकार को vndservice_manager_type में बदलना होगा और नियम को vndservice.te फ़ाइल में ले जाना होगा। उदाहरण:

type atfwd_service,      vndservice_manager_type;

सेवा प्रबंधक नियम

पहले, नियम डोमेन को servicemanager से सेवाएं जोड़ने या खोजने की अनुमति देते थे। उदाहरण:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;

एंड्रॉइड 8 में, ऐसे नियम यथावत रह सकते हैं और उसी वर्ग का उपयोग कर सकते हैं। उदाहरण:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;