डिवाइस की सुरक्षा को बेहतर बनाने के लिए, Android 7.0 ने एक ही प्रोसेस वाली mediaserver
प्रोसेस को कई प्रोसेस में बांटा है. साथ ही, हर प्रोसेस के लिए ज़रूरी अनुमतियों और सुविधाओं को सीमित किया है. इन बदलावों से, मीडिया फ़्रेमवर्क की सुरक्षा से जुड़ी जोखिम की संभावनाओं को कम करने में मदद मिलती है. इसके लिए, ये काम किए जाते हैं:
- एवी पाइपलाइन कॉम्पोनेंट को, ऐप्लिकेशन के हिसाब से सैंडबॉक्स की गई प्रोसेस में बांटना.
- अपडेट किए जा सकने वाले मीडिया कंपोनेंट (एक्सट्रैक्टर, कोडेक वगैरह) चालू करना.
इन बदलावों से, मीडिया से जुड़ी ज़्यादातर सुरक्षा से जुड़ी कमज़ोरियों को कम करने में मदद मिलती है. इससे, असली उपयोगकर्ताओं के डिवाइस और डेटा सुरक्षित रहते हैं.
OEM और SoC वेंडर को अपने एचएएल और फ़्रेमवर्क में बदलाव करने होंगे, ताकि उन्हें नए आर्किटेक्चर के साथ काम करने लायक बनाया जा सके. खास तौर पर, वेंडर के दिए गए Android कोड में अक्सर यह माना जाता है कि सभी चीज़ें एक ही प्रोसेस में चलती हैं. इसलिए, वेंडर को अपने कोड को अपडेट करना होगा, ताकि वे नेटिव हैंडल (native_handle
) पास कर सकें. इन हैंडल का इस्तेमाल सभी प्रोसेस में किया जा सकता है. मीडिया को सुरक्षित बनाने से जुड़े बदलावों को लागू करने के बारे में जानने के लिए, frameworks/av
और
frameworks/native
देखें.
आर्किटेक्चर में बदलाव
Android के पिछले वर्शन में, एक ही mediaserver
प्रोसेस का इस्तेमाल किया जाता था. इसमें कई अनुमतियां होती थीं, जैसे कि कैमरे का ऐक्सेस, ऑडियो का ऐक्सेस, वीडियो ड्राइवर का ऐक्सेस, फ़ाइल का ऐक्सेस, नेटवर्क का ऐक्सेस वगैरह. Android
7.0, mediaserver
प्रोसेस को कई नई प्रोसेस में बांटता है. इनमें से हर प्रोसेस के लिए, अनुमतियों के काफ़ी कम सेट की ज़रूरत होती है:
पहली इमेज. मीडिया सर्वर को ज़्यादा सुरक्षित बनाने के लिए, आर्किटेक्चर में किए गए बदलाव
इस नए आर्किटेक्चर से यह पक्का होता है कि अगर किसी प्रोसेस में छेड़छाड़ की जाती है, तो भी नुकसान पहुंचाने वाले कोड के पास उन अनुमतियों का ऐक्सेस नहीं होता जो पहले mediaserver
के पास थीं. प्रोसेस पर SELinux और seccomp नीतियों की पाबंदियां होती हैं.
ध्यान दें: वेंडर डिपेंडेंसी की वजह से, कुछ कोडेक अब भी mediaserver
में चलते हैं. इसलिए, वे mediaserver
को ज़रूरत से ज़्यादा अनुमतियां देते हैं. खास तौर पर, Android 7.0 के लिए mediaserver
में Widevine Classic काम करता रहेगा.
MediaServer में हुए बदलाव
Android 7.0 में, mediaserver
प्रोसेस, वीडियो चलाने और रिकॉर्ड करने के लिए मौजूद है. उदाहरण के लिए, कॉम्पोनेंट और प्रोसेस के बीच बफ़र को पास करना और सिंक करना. प्रोसेस, स्टैंडर्ड Binder
mechanism के ज़रिए एक-दूसरे से संपर्क करती हैं.
किसी स्टैंडर्ड लोकल फ़ाइल को चलाने के सेशन में, ऐप्लिकेशन mediaserver
को एक फ़ाइल डिस्क्रिप्टर (FD) भेजता है. आम तौर पर, यह MediaPlayer Java API के ज़रिए भेजा जाता है. इसके बाद, mediaserver
:
- यह FD को Binder DataSource ऑब्जेक्ट में रैप करता है. इसे एक्सट्रैक्टर प्रोसेस को पास किया जाता है, जो Binder IPC का इस्तेमाल करके फ़ाइल से पढ़ने के लिए इसका इस्तेमाल करता है. (mediaextractor को FD नहीं मिलता, बल्कि डेटा पाने के लिए वह
mediaserver
को फिर से Binder कॉल करता है.) - यह फ़ाइल की जांच करता है और फ़ाइल टाइप (उदाहरण के लिए, MP3Extractor या MPEG4Extractor) के लिए सही एक्सट्रैक्टर बनाता है. साथ ही,
mediaserver
प्रोसेस के लिए, एक्सट्रैक्टर का Binder इंटरफ़ेस दिखाता है. - फ़ाइल में मौजूद डेटा का टाइप (जैसे, MP3 या H.264 डेटा) तय करने के लिए, एक्सट्रैक्टर को Binder IPC कॉल करता है.
- ज़रूरी टाइप के कोडेक बनाने के लिए,
mediacodec
प्रोसेस को कॉल करता है. साथ ही, इन कोडेक के लिए Binder इंटरफ़ेस पाता है. - एन्क्रिप्ट किए गए सैंपल पढ़ने के लिए, एक्सट्रैक्टर को बार-बार Binder IPC कॉल करता है. साथ ही, डिकोड करने के लिए
mediacodec
प्रोसेस में एन्क्रिप्ट किया गया डेटा भेजने के लिए, Binder IPC का इस्तेमाल करता है और डिकोड किया गया डेटा पाता है.
कुछ इस्तेमाल के उदाहरणों में, कोई कोडेक शामिल नहीं होता. जैसे, ऑफ़लोड किया गया वीडियो चलाना, जहां कोड में बदला गया डेटा सीधे आउटपुट डिवाइस पर भेजा जाता है. इसके अलावा, कोडेक, डिकोड किए गए डेटा (वीडियो चलाना) के बफ़र को दिखाने के बजाय, डिकोड किए गए डेटा को सीधे रेंडर कर सकता है.
MediaCodecService में हुए बदलाव
कोडेक सेवा में एन्कोडर और डिकोडर मौजूद होते हैं. वेंडर डिपेंडेंसी की वजह से, अभी तक सभी कोडेक कोडेक प्रोसेस में शामिल नहीं हैं. Android 7.0 में:
- कोडेक प्रोसेस में, सुरक्षित नहीं होने वाले डिकोडर और सॉफ़्टवेयर एन्कोडर मौजूद होते हैं.
- सुरक्षित डिकोडर और हार्डवेयर एन्कोडर,
mediaserver
(बदलाव नहीं हुआ) में मौजूद हैं.
कोई ऐप्लिकेशन (या mediaserver
) कोडेक प्रोसेस को कॉल करता है, ताकि ज़रूरी टाइप का कोडेक बनाया जा सके. इसके बाद, कोडेक को कॉल करके कोड में बदले गए डेटा को पास किया जाता है और डीकोड किए गए डेटा को वापस पाया जाता है (डीकोड करने के लिए). इसके अलावा, डीकोड किए गए डेटा को पास करके कोड में बदले गए डेटा को वापस पाया जाता है (कोड में बदलने के लिए). कोडेक में और उससे डेटा ट्रांसफ़र करने के लिए, पहले से ही शेयर की गई मेमोरी का इस्तेमाल किया जाता है. इसलिए, उस प्रोसेस में कोई बदलाव नहीं हुआ है.
MediaDrmServer में हुए बदलाव
डीआरएम सर्वर का इस्तेमाल, डीआरएम से सुरक्षित कॉन्टेंट चलाते समय किया जाता है. जैसे, Google Play Movies में मौजूद फ़िल्में. यह एन्क्रिप्ट (सुरक्षित) किए गए डेटा को सुरक्षित तरीके से डिक्रिप्ट (अनचाहे कोड को हटाना) करता है. इसलिए, इसके पास सर्टिफ़िकेट, कुंजी के स्टोरेज, और अन्य संवेदनशील कॉम्पोनेंट का ऐक्सेस होता है. वेंडर डिपेंडेंसी की वजह से, डीआरएम प्रोसेस का इस्तेमाल अब तक सभी मामलों में नहीं किया जा रहा है.
AudioServer में हुए बदलाव
AudioServer प्रोसेस, ऑडियो से जुड़े कॉम्पोनेंट को होस्ट करती है. जैसे, ऑडियो इनपुट और आउटपुट, नीति मैनेजर सेवा, जो ऑडियो रूटिंग तय करती है, और एफ़एम रेडियो सेवा. ऑडियो में हुए बदलावों और उन्हें लागू करने के दिशा-निर्देशों के बारे में जानने के लिए, ऑडियो लागू करना लेख पढ़ें.
CameraServer में हुए बदलाव
CameraServer, कैमरे को कंट्रोल करता है. इसका इस्तेमाल वीडियो रिकॉर्ड करते समय, कैमरे से वीडियो फ़्रेम पाने के लिए किया जाता है. इसके बाद, इन्हें आगे की प्रोसेसिंग के लिए mediaserver
को भेजा जाता है. CameraServer में हुए बदलावों और उन्हें लागू करने के बारे में जानकारी पाने के लिए, कैमरा फ़्रेमवर्क को बेहतर बनाना लेख पढ़ें.
ExtractorService में हुए बदलाव
एक्सट्रैक्टर सेवा, एक्सट्रैक्टर को होस्ट करती है. ये ऐसे कॉम्पोनेंट होते हैं जो मीडिया फ़्रेमवर्क के साथ काम करने वाले अलग-अलग फ़ाइल फ़ॉर्मैट को पार्स करते हैं. एक्सट्रैक्टर सेवा, सभी सेवाओं में सबसे कम सुविधाओं वाली सेवा है. यह एफ़डी नहीं पढ़ सकती. इसलिए, फ़ाइलों को ऐक्सेस करने के लिए, यह किसी बाइंडर इंटरफ़ेस (mediaserver for
हर प्लेबैक सेशन से इसे मिलता है) पर कॉल करती है.
कोई ऐप्लिकेशन (या mediaserver
), IMediaExtractor
पाने के लिए एक्सट्रैक्टर प्रोसेस को कॉल करता है. इसके बाद, फ़ाइल में मौजूद ट्रैक के लिए IMediaSources
पाने के लिए, उस IMediaExtractor
को कॉल करता है. इसके बाद, उनसे डेटा पढ़ने के लिए IMediaSources
को कॉल करता है.
डेटा को एक प्रोसेस से दूसरी प्रोसेस में ट्रांसफ़र करने के लिए, ऐप्लिकेशन (या mediaserver
) रिप्लाई-पर्सल में डेटा को बाइंडर ट्रांज़ैक्शन के हिस्से के तौर पर शामिल करता है या शेयर की गई मेमोरी का इस्तेमाल करता है:
- शेयर की गई मेमोरी का इस्तेमाल करने के लिए, शेयर की गई मेमोरी को रिलीज़ करने के लिए एक अतिरिक्त Binder कॉल की ज़रूरत होती है. हालांकि, यह तेज़ है और बड़े बफ़र के लिए कम पावर का इस्तेमाल करता है.
- इन-पर्सल का इस्तेमाल करने के लिए, अतिरिक्त कॉपी करने की ज़रूरत होती है. हालांकि, यह तेज़ होता है और 64 केबी से छोटे बफ़र के लिए कम पावर का इस्तेमाल करता है.
लागू करना
MediaDrm
और MediaCrypto
कॉम्पोनेंट को नई mediadrmserver
प्रोसेस में ट्रांसफ़र करने के लिए, वेंडर को सुरक्षित बफ़र के लिए, बफ़र को प्रोसेस के बीच शेयर करने की अनुमति देने के लिए, बफ़र के लिए ऐलोकेशन का तरीका बदलना होगा.
Android के पिछले वर्शन में, सुरक्षित बफ़र OMX::allocateBuffer
के ज़रिए mediaserver
में असाइन किए जाते हैं. साथ ही, डिक्रिप्ट करने के दौरान, उसी प्रोसेस में इनका इस्तेमाल किया जाता है, जैसा कि यहां दिखाया गया है:
दूसरी इमेज. Android 6.0 और इससे पहले के वर्शन के लिए, मीडिया सर्वर में बफ़र का ऐलोकेशन.
Android 7.0 में, बफ़र को असाइन करने की प्रोसेस को एक नए तरीके से बदल दिया गया है. इससे, मौजूदा प्रोसेस पर कम से कम असर पड़ता है और आपको ज़्यादा सुविधाएं मिलती हैं. नई mediadrmserver
प्रोसेस में MediaDrm
और MediaCrypto
स्टैक के साथ, बफ़र को अलग-अलग तरीके से असाइन किया जाता है. साथ ही, वेंडर को सुरक्षित बफ़र हैंडल अपडेट करने होंगे, ताकि MediaCodec
के MediaCrypto
पर डिक्रिप्ट करने की प्रोसेस शुरू करने पर, उन्हें बाइंडर में ट्रांसफ़र किया जा सके.
तीसरी इमेज. Android 7.0 और इसके बाद के वर्शन में, मीडिया सर्वर में बफ़र के लिए जगह तय करना.
नेटिव हैंडल का इस्तेमाल करना
OMX::allocateBuffer
को native_handle
स्ट्रक्चर का पॉइंटर दिखाना चाहिए. इसमें फ़ाइल डिस्क्रिप्टर (FDs) और अतिरिक्त पूर्णांक डेटा शामिल होता है. native_handle
में एफ़डी इस्तेमाल करने के सभी फ़ायदे होते हैं. जैसे, क्रम से लगाने/क्रम से हटाने के लिए मौजूदा बाइंडर की सहायता. साथ ही, यह उन वेंडर के लिए ज़्यादा सुविधाजनक होता है जो फ़िलहाल एफ़डी का इस्तेमाल नहीं करते.
नेटिव हैंडल को असाइन करने के लिए, native_handle_create()
का इस्तेमाल करें.
फ़्रेमवर्क कोड, डिस्ट्रिब्यूट किए गए native_handle
स्ट्रक्चर का मालिकाना हक लेता है. साथ ही, native_handle
को मूल रूप से डिस्ट्रिब्यूट करने और उसे डिससिरियलाइज़ करने, दोनों प्रोसेस में संसाधनों को रिलीज़ करने की ज़िम्मेदारी भी इसकी होती है. फ़्रेमवर्क, नेटिव हैंडल को native_handle_close()
के बाद
native_handle_delete()
के साथ रिलीज़ करता है. साथ ही, Parcel::writeNativeHandle()/readNativeHandle()
का इस्तेमाल करके native_handle
को सीरियलाइज़/डिस सीरियलाइज़ करता है.
सुरक्षित बफ़र दिखाने के लिए एफ़डी का इस्तेमाल करने वाले SoC वेंडर, native_handle
में अपने एफ़डी की जानकारी भर सकते हैं. एफ़डी का इस्तेमाल न करने वाले वेंडर, native_buffer
में अतिरिक्त फ़ील्ड का इस्तेमाल करके सुरक्षित बफ़र दिखा सकते हैं.
डिक्रिप्ट करने की जगह सेट करना
वेंडर को native_handle
पर काम करने वाले OEMCrypto डिक्रिप्ट करने के तरीके को अपडेट करना होगा. ऐसा इसलिए ज़रूरी है, ताकि वेंडर के हिसाब से ज़रूरी कार्रवाइयां की जा सकें और native_handle
को नए प्रोसेस स्पेस में इस्तेमाल किया जा सके. आम तौर पर, बदलावों में OEMCrypto लाइब्रेरी के अपडेट शामिल होते हैं.
allocateBuffer
एक स्टैंडर्ड OMX ऑपरेशन है. इसलिए, Android 7.0 में इस सहायता के लिए क्वेरी करने के लिए, एक नया OMX एक्सटेंशन (OMX.google.android.index.allocateNativeHandle
) और OMX_SetParameter
कॉल शामिल है. यह कॉल, OMX लागू करने के लिए सूचना देता है कि उसे नेटिव हैंडल का इस्तेमाल करना चाहिए.