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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

vndbinder

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

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

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

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

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

vndservicemanager

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

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

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

SELinux नीति

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

  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

एंड्रॉइड 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;