Android में, Automotive HIDL हार्डवेयर ऐब्स्ट्रैक्शन लेयर (एचएएल) शामिल है. यह Android बूट प्रोसेस के शुरुआती चरण में इमेज कैप्चर और डिसप्ले करने की सुविधा देता है. साथ ही, यह सिस्टम के बंद होने तक काम करता रहता है. एचएएल में एक्सटीरियर व्यू सिस्टम (ईवीएस) स्टैक शामिल होता है. इसका इस्तेमाल आम तौर पर, Android पर आधारित इन-व्हीकल इन्फ़ोटेनमेंट (आईवीआई) सिस्टम वाले वाहनों में, रियरव्यू कैमरे और सराउंड व्यू डिसप्ले को सपोर्ट करने के लिए किया जाता है. ईवीएस, उपयोगकर्ता के ऐप्लिकेशन में बेहतर सुविधाएं लागू करने की अनुमति भी देता है.
Android में, ईवीएस के लिए खास तौर पर बनाया गया कैप्चर और डिसप्ले ड्राइवर इंटरफ़ेस (/hardware/interfaces/automotive/evs/1.0
में) भी शामिल है. हालांकि, Android के मौजूदा कैमरा और डिसप्ले सेवाओं के आधार पर, पीछे का कैमरा दिखाने वाला ऐप्लिकेशन बनाया जा सकता है. हालांकि, ऐसा ऐप्लिकेशन Android बूट प्रोसेस में बहुत देर से चलेगा. डेडीकेटेड एचएएल का इस्तेमाल करने से, इंटरफ़ेस को बेहतर तरीके से मैनेज किया जा सकता है. साथ ही, इससे यह भी पता चलता है कि ओईएम को ईवीएस स्टैक के साथ काम करने के लिए, क्या-क्या लागू करना होगा.
सिस्टम कॉम्पोनेंट
ईवीएस में ये सिस्टम कॉम्पोनेंट शामिल होते हैं:

पहली इमेज. ईवीएस सिस्टम के कॉम्पोनेंट के बारे में खास जानकारी.
ईवीएस ऐप्लिकेशन
C++ का एक सैंपल ईवीएस ऐप्लिकेशन
(/packages/services/Car/evs/app
) रेफ़रंस के तौर पर काम करता है. यह ऐप्लिकेशन, ईवीएस मैनेजर से वीडियो फ़्रेम का अनुरोध करने और डिसप्ले के लिए तैयार फ़्रेम को वापस ईवीएस मैनेजर को भेजने के लिए ज़िम्मेदार होता है.
यह EVS और Car Service के उपलब्ध होते ही, init से शुरू होने की उम्मीद करता है. इसे पावर चालू होने के दो (2) सेकंड के अंदर शुरू किया जाना चाहिए. ओईएम, ईवीएस ऐप्लिकेशन में अपनी पसंद के मुताबिक बदलाव कर सकते हैं या उसे बदल सकते हैं.
EVS Manager
ईवीएस मैनेजर (/packages/services/Car/evs/manager
), ईवीएस ऐप्लिकेशन को ज़रूरी बिल्डिंग ब्लॉक उपलब्ध कराता है. इनकी मदद से, ईवीएस ऐप्लिकेशन रियरव्यू कैमरे के डिसप्ले से लेकर 6DOF मल्टी-कैमरा रेंडरिंग तक कुछ भी लागू कर सकता है. इसका इंटरफ़ेस, HIDL के ज़रिए दिखाया जाता है. इसे एक साथ कई क्लाइंट के अनुरोध स्वीकार करने के लिए बनाया गया है.
अन्य ऐप्लिकेशन और सेवाएं (खास तौर पर कार की सेवा) EVS मैनेजर की स्थिति के बारे में क्वेरी कर सकती हैं. इससे उन्हें यह पता चलता है कि ईवीएस सिस्टम कब चालू है.
ईवीएस एचआईडीएल इंटरफ़ेस
ईवीएस सिस्टम, कैमरा, और डिसप्ले एलिमेंट, दोनों को android.hardware.automotive.evs
पैकेज में तय किया गया है. /hardware/interfaces/automotive/evs/1.0/default
में, इंटरफ़ेस का इस्तेमाल करने वाला एक सैंपल दिया गया है. इसमें टेस्ट के लिए अप्राकृतिक इमेज जनरेट की जाती हैं और यह पुष्टि की जाती है कि इमेज राउंड ट्रिप करती हैं.
OEM, /hardware/interfaces/automotive/evs
में मौजूद .hal फ़ाइलों के ज़रिए बताए गए एपीआई को लागू करने के लिए ज़िम्मेदार होता है. इस तरह के इंटिग्रेशन, फ़िज़िकल कैमरों से डेटा इकट्ठा करने और उसे कॉन्फ़िगर करने के लिए ज़िम्मेदार होते हैं. साथ ही, वे इसे Gralloc से पहचाने जा सकने वाले शेयर किए गए मेमोरी बफ़र के ज़रिए डिलीवर करते हैं. डिसप्ले साइड पर लागू करने की प्रोसेस में, शेयर किया गया मेमोरी बफ़र उपलब्ध कराने की ज़िम्मेदारी होती है. इसे ऐप्लिकेशन भर सकता है. आम तौर पर, यह काम EGL रेंडरिंग के ज़रिए किया जाता है. साथ ही, इसमें तैयार किए गए फ़्रेम को किसी भी ऐसी चीज़ के मुकाबले प्राथमिकता दी जाती है जो फ़िज़िकल डिसप्ले पर दिख सकती है. ईवीएस इंटरफ़ेस को लागू करने वाले वेंडर की जानकारी, /vendor/… /device/…
या hardware/…
में सेव की जा सकती है. उदाहरण के लिए,
/hardware/[vendor]/[platform]/evs
).
कर्नेल ड्राइवर
EVS स्टैक के साथ काम करने वाले डिवाइस के लिए, कर्नेल ड्राइवर ज़रूरी होते हैं. नए ड्राइवर बनाने के बजाय, ओईएम के पास मौजूदा कैमरे और/या डिसप्ले हार्डवेयर ड्राइवर के ज़रिए, ईवीएस के लिए ज़रूरी सुविधाओं को सपोर्ट करने का विकल्प होता है. ड्राइवर का दोबारा इस्तेमाल करना फ़ायदेमंद हो सकता है. खास तौर पर, डिसप्ले ड्राइवर के लिए. ऐसा इसलिए, क्योंकि इमेज प्रज़ेंटेशन के लिए अन्य ऐक्टिव थ्रेड के साथ समन्वय करना पड़ सकता है. Android 8.0 में, v4l2 पर आधारित एक सैंपल ड्राइवर (packages/services/Car/evs/sampleDriver
में) शामिल है. यह v4l2 के लिए कर्नल पर और आउटपुट इमेज दिखाने के लिए SurfaceFlinger पर निर्भर करता है.
ईवीएस हार्डवेयर इंटरफ़ेस की जानकारी
इस सेक्शन में, एचएएल के बारे में बताया गया है. वेंडर से उम्मीद की जाती है कि वे इस एपीआई को अपने हार्डवेयर के हिसाब से लागू करें.
IEvsEnumerator
यह ऑब्जेक्ट, सिस्टम में उपलब्ध ईवीएस हार्डवेयर की गिनती करने के लिए ज़िम्मेदार होता है. जैसे, एक या उससे ज़्यादा कैमरे और एक डिसप्ले डिवाइस.
getCameraList() generates (vec<CameraDesc> cameras);
यह फ़ंक्शन, सिस्टम में मौजूद सभी कैमरों की जानकारी देने वाला एक वेक्टर दिखाता है. यह माना जाता है कि कैमरों का सेट तय है और बूट टाइम पर इसके बारे में जानकारी मिल जाती है. कैमरे की जानकारी के बारे में ज़्यादा जानने के लिए, CameraDesc
देखें.
openCamera(string camera_id) generates (IEvsCamera camera);
यह फ़ंक्शन, एक इंटरफ़ेस ऑब्जेक्ट हासिल करता है. इसका इस्तेमाल, किसी खास कैमरे से इंटरैक्ट करने के लिए किया जाता है. इस कैमरे की पहचान, यूनीक camera_id स्ट्रिंग से होती है. अगर फ़ंक्शन काम नहीं करता है, तो यह NULL दिखाता है.
पहले से खुले हुए कैमरे को फिर से खोलने की कोशिश करने पर, ऐसा नहीं हो सकता कि कैमरा न खुले. ऐप्लिकेशन के चालू और बंद होने से जुड़ी रेस कंडीशन से बचने के लिए, कैमरे को फिर से खोलने पर पिछले इंस्टेंस को बंद कर देना चाहिए, ताकि नए अनुरोध को पूरा किया जा सके. इस तरह से रोके गए कैमरे के इंस्टेंस को बंद कर दिया जाना चाहिए. साथ ही, इसे पूरी तरह से बंद होने तक इंतज़ार करना चाहिए. इसके अलावा, कैमरे की स्थिति पर असर डालने वाले किसी भी अनुरोध का जवाब, OWNERSHIP_LOST
के रिटर्न कोड के साथ देना चाहिए.
closeCamera(IEvsCamera camera);
यह IEvsCamera इंटरफ़ेस को रिलीज़ करता है. यह openCamera()
कॉल के उलट है. closeCamera
को कॉल करने से पहले, stopVideoStream()
को कॉल करके कैमरा वीडियो स्ट्रीम बंद करनी होगी.
openDisplay() generates (IEvsDisplay display);
यह एक इंटरफ़ेस ऑब्जेक्ट हासिल करता है. इसका इस्तेमाल सिर्फ़ सिस्टम के ईवीएस डिसप्ले के साथ इंटरैक्ट करने के लिए किया जाता है. एक समय में, सिर्फ़ एक क्लाइंट के पास IEvsDisplay का फ़ंक्शनल इंस्टेंस हो सकता है. openCamera
में बताए गए, एग्रेसिव ओपन बिहेवियर की तरह ही, IEvsDisplay ऑब्जेक्ट को कभी भी बनाया जा सकता है. इससे पिछले सभी इंस्टेंस बंद हो जाएंगे. अमान्य किए गए इंस्टेंस मौजूद रहते हैं और अपने मालिकों से फ़ंक्शन कॉल का जवाब देते हैं. हालांकि, बंद होने पर उन्हें कोई भी बदलाव नहीं करना चाहिए. आखिरकार, क्लाइंट ऐप्लिकेशन को OWNERSHIP_LOST
गड़बड़ी के रिटर्न कोड का पता चल जाता है. इसके बाद, वह बंद हो जाता है और इनऐक्टिव इंटरफ़ेस को रिलीज़ कर देता है.
closeDisplay(IEvsDisplay display);
यह IEvsDisplay इंटरफ़ेस को रिलीज़ करता है. यह openDisplay()
कॉल के उलट काम करता है. getTargetBuffer()
कॉल के ज़रिए मिले सभी बफ़र, डिसप्ले बंद करने से पहले डिसप्ले को वापस किए जाने चाहिए.
getDisplayState() generates (DisplayState state);
डिसप्ले की मौजूदा स्थिति का पता चलता है. HAL को मौजूदा स्थिति की जानकारी देनी चाहिए. यह जानकारी, हाल ही में अनुरोध की गई स्थिति से अलग हो सकती है.
डिस्प्ले की स्थितियों को बदलने के लिए ज़िम्मेदार लॉजिक, डिवाइस लेयर के ऊपर होना चाहिए. इससे HAL को डिस्प्ले की स्थितियों को अपने-आप बदलने से रोका जा सकेगा. अगर डिसप्ले को फ़िलहाल किसी क्लाइंट ने होल्ड नहीं किया है (openDisplay को कॉल करके), तो यह फ़ंक्शन NOT_OPEN
दिखाता है. इसके अलावा, यह ईवीएस डिसप्ले की मौजूदा स्थिति की जानकारी देता है. इसके लिए, IEvsDisplay API देखें.
struct CameraDesc { string camera_id; int32 vendor_flags; // Opaque value }
camera_id
. यह एक स्ट्रिंग होती है, जो किसी कैमरे की खास तौर पर पहचान करती है. यह डिवाइस का कर्नल डिवाइस नेम या डिवाइस का नाम हो सकता है. जैसे, rearview. इस स्ट्रिंग की वैल्यू, HAL लागू करने वाला व्यक्ति चुनता है. इसका इस्तेमाल ऊपर मौजूद स्टैक करता है.vendor_flags
. यह ड्राइवर से कस्टम ईवीएस ऐप्लिकेशन तक, खास कैमरा जानकारी को ओपेक तरीके से पास करने का एक तरीका है. इसे ड्राइवर से ईवीएस ऐप्लिकेशन तक बिना किसी बदलाव के पास किया जाता है. ईवीएस ऐप्लिकेशन के पास इसे अनदेखा करने का विकल्प होता है.
IEvsCamera
यह ऑब्जेक्ट, एक कैमरे को दिखाता है. साथ ही, इमेज कैप्चर करने के लिए मुख्य इंटरफ़ेस है.
getCameraInfo() generates (CameraDesc info);
इस कैमरे के CameraDesc
दिखाता है.
setMaxFramesInFlight(int32 bufferCount) generates (EvsResult result);
इससे यह तय होता है कि कैमरे को बफ़र चेन की कितनी डेप्थ के साथ काम करने के लिए कहा गया है. IEvsCamera का क्लाइंट, एक साथ इतने फ़्रेम होल्ड कर सकता है. अगर इतने फ़्रेम, doneWithFrame
से वापस नहीं किए जाते हैं, तो स्ट्रीम फ़्रेम छोड़ देती है. ऐसा तब तक होता है, जब तक कि बफ़र को फिर से इस्तेमाल करने के लिए वापस नहीं किया जाता. यह कॉल कभी भी आ सकता है. भले ही, स्ट्रीम पहले से चल रही हों. ऐसे में, चेन में बफ़र को ज़रूरत के हिसाब से जोड़ा या हटाया जाना चाहिए. अगर इस एंट्री पॉइंट पर कोई कॉल नहीं किया जाता है, तो IEvsCamera डिफ़ॉल्ट रूप से कम से कम एक फ़्रेम का समर्थन करता है. हालांकि, इससे ज़्यादा फ़्रेम भी स्वीकार किए जा सकते हैं.
अगर अनुरोध किया गया bufferCount नहीं मिल पाता है, तो फ़ंक्शन BUFFER_NOT_AVAILABLE
या अन्य काम का गड़बड़ी कोड दिखाता है. इस मामले में, सिस्टम पहले से सेट की गई वैल्यू के साथ काम करता रहता है.
startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);
यह अनुरोध, इस कैमरे से ईवीएस कैमरा फ़्रेम डिलीवर करने के लिए किया जाता है. IEvsCameraStream को नए इमेज फ़्रेम के साथ समय-समय पर कॉल मिलना शुरू हो जाता है. ऐसा तब तक होता है, जब तक stopVideoStream()
को कॉल नहीं किया जाता. फ़्रेम, startVideoStream
कॉल के 500 मिलीसेकंड के अंदर डिलीवर होने शुरू हो जाने चाहिए. साथ ही, शुरू होने के बाद, कम से कम 10 एफ़पीएस पर जनरेट होने चाहिए. वीडियो स्ट्रीम शुरू होने में लगने वाला समय, रियरव्यू कैमरे के चालू होने में लगने वाले समय की ज़रूरी शर्त के हिसाब से गिना जाता है. अगर स्ट्रीम शुरू नहीं की गई है, तो गड़बड़ी का कोड दिखना चाहिए. ऐसा न होने पर, 'ठीक है' कोड दिखता है.
oneway doneWithFrame(BufferDesc buffer);
IEvsCameraStream को डिलीवर किया गया फ़्रेम दिखाता है. IEvsCameraStream इंटरफ़ेस को डिलीवर किए गए फ़्रेम का इस्तेमाल करने के बाद, फ़्रेम को IEvsCamera पर वापस भेजना होगा, ताकि उसका फिर से इस्तेमाल किया जा सके. बफ़र की संख्या सीमित होती है. ऐसा हो सकता है कि बफ़र की संख्या सिर्फ़ एक हो. अगर बफ़र खत्म हो जाते हैं, तो जब तक कोई बफ़र वापस नहीं आ जाता, तब तक कोई और फ़्रेम डिलीवर नहीं किया जाता. इससे फ़्रेम स्किप हो सकते हैं. नल हैंडल वाला बफ़र, स्ट्रीम के खत्म होने का मतलब होता है. इसे इस फ़ंक्शन के ज़रिए वापस नहीं किया जाना चाहिए. अगर अनुरोध पूरा हो जाता है, तो यह फ़ंक्शन OK दिखाता है. अगर अनुरोध पूरा नहीं होता है, तो यह गड़बड़ी का सही कोड दिखाता है. इसमें INVALID_ARG
या BUFFER_NOT_AVAILABLE
शामिल हो सकता है.
stopVideoStream();
इससे ईवीएस कैमरे के फ़्रेम की डिलीवरी बंद हो जाती है. डिलीवरी एसिंक्रोनस होने की वजह से, इस कॉल के वापस आने के बाद भी कुछ समय तक फ़्रेम मिलते रहेंगे. हर फ़्रेम को तब तक वापस भेजना होगा, जब तक IEvsCameraStream को स्ट्रीम बंद होने का सिग्नल नहीं मिल जाता. ऐसी स्ट्रीम पर stopVideoStream
को कॉल करना कानूनी है जिसे पहले ही बंद कर दिया गया हो या कभी शुरू ही न किया गया हो. ऐसे मामलों में, इसे अनदेखा कर दिया जाता है.
getExtendedInfo(int32 opaqueIdentifier) generates (int32 value);
यह एचएएल के लागू होने के तरीके से, ड्राइवर के बारे में जानकारी का अनुरोध करता है. opaqueIdentifier
के लिए मान्य वैल्यू, ड्राइवर के हिसाब से तय की जाती हैं. हालांकि, कोई भी वैल्यू पास न करने पर ड्राइवर क्रैश हो सकता है. ड्राइवर को, किसी भी ऐसे opaqueIdentifier
के लिए 0 वैल्यू देनी चाहिए जिसे वह नहीं पहचानता.
setExtendedInfo(int32 opaqueIdentifier, int32 opaqueValue) generates (EvsResult result);
यह ड्राइवर के लिए खास वैल्यू को एचएएल लागू करने वाले कॉम्पोनेंट को भेजता है. यह एक्सटेंशन सिर्फ़ वाहन के हिसाब से एक्सटेंशन उपलब्ध कराने के लिए दिया जाता है. साथ ही, HAL को डिफ़ॉल्ट स्थिति में काम करने के लिए, इस कॉल की ज़रूरत नहीं होनी चाहिए. अगर ड्राइवर वैल्यू को पहचानता है और स्वीकार करता है, तो OK लौटाया जाना चाहिए. ऐसा न होने पर, INVALID_ARG
या गड़बड़ी का कोई अन्य कोड लौटाया जाना चाहिए.
struct BufferDesc { uint32 width; // Units of pixels uint32 height; // Units of pixels uint32 stride; // Units of pixels uint32 pixelSize; // Size of single pixel in bytes uint32 format; // May contain values from android_pixel_format_t uint32 usage; // May contain values from Gralloc.h uint32 bufferId; // Opaque value handle memHandle; // gralloc memory buffer handle }
एपीआई के ज़रिए पास की गई इमेज के बारे में बताता है. इमेज बफ़र के बारे में बताने के लिए, इस स्ट्रक्चर को भरने की ज़िम्मेदारी एचएएल ड्राइव की होती है. साथ ही, एचएएल क्लाइंट को इस स्ट्रक्चर को सिर्फ़ पढ़ने के तौर पर इस्तेमाल करना चाहिए. इन फ़ील्ड में इतनी जानकारी होती है कि क्लाइंट, ANativeWindowBuffer
ऑब्जेक्ट को फिर से बना सकता है. ऐसा तब किया जा सकता है, जब eglCreateImageKHR()
एक्सटेंशन के ज़रिए EGL के साथ इमेज का इस्तेमाल करना ज़रूरी हो.
width
. दिखाई गई इमेज की चौड़ाई, पिक्सल में.height
. दिखाई गई इमेज की ऊंचाई, पिक्सल में.stride
. हर लाइन के लिए मेमोरी में इस्तेमाल किए गए पिक्सल की संख्या. इसमें लाइनों को अलाइन करने के लिए इस्तेमाल की गई पैडिंग भी शामिल है. इसे पिक्सल में दिखाया जाता है, ताकि gralloc के बफ़र के ब्यौरे के लिए इस्तेमाल किए गए कन्वेंशन से मेल खा सके.pixelSize
. हर पिक्सल के लिए इस्तेमाल किए गए बाइट की संख्या. इससे इमेज में लाइनों के बीच में जाने के लिए ज़रूरी बाइट के साइज़ का हिसाब लगाया जा सकता है (stride
बाइट में =stride
पिक्सल में *pixelSize
).format
. इमेज में इस्तेमाल किया गया पिक्सल फ़ॉर्मैट. दिया गया फ़ॉर्मैट, प्लैटफ़ॉर्म के OpenGL वर्शन के साथ काम करना चाहिए. संगतता की जांच पास करने के लिए, कैमरे के इस्तेमाल के लिएHAL_PIXEL_FORMAT_YCRCB_420_SP
को प्राथमिकता दी जानी चाहिए. साथ ही, डिसप्ले के लिएRGBA
याBGRA
को प्राथमिकता दी जानी चाहिए.usage
. HAL लागू करने के तरीके से सेट किए गए इस्तेमाल के फ़्लैग. HAL क्लाइंट को इन फ़्लैग को बिना बदलाव किए पास करना होगा. ज़्यादा जानकारी के लिए,Gralloc.h
से जुड़े फ़्लैग देखें.bufferId
. यह एक यूनीक वैल्यू है. इसे HAL लागू करने वाला व्यक्ति तय करता है, ताकि HAL API के ज़रिए राउंड ट्रिप के बाद बफ़र को पहचाना जा सके. इस फ़ील्ड में सेव की गई वैल्यू को HAL लागू करने वाला व्यक्ति अपनी मर्ज़ी से चुन सकता है.memHandle
. यह इमेज डेटा वाले मेमोरी बफ़र का हैंडल है. HAL लागू करने वाला व्यक्ति, यहां Gralloc बफ़र हैंडल को सेव कर सकता है.
IEvsCameraStream
क्लाइंट इस इंटरफ़ेस को लागू करता है, ताकि एसिंक्रोनस वीडियो फ़्रेम डिलीवर किए जा सकें.
deliverFrame(BufferDesc buffer);
जब भी वीडियो फ़्रेम की जांच के लिए तैयार होता है, तब यह एचएएल से कॉल पाता है.
इस तरीके से मिले बफ़र को IEvsCamera::doneWithFrame()
को कॉल करके वापस करना होगा. IEvsCamera::stopVideoStream()
को कॉल करके वीडियो स्ट्रीम बंद करने पर, यह कॉलबैक तब तक जारी रह सकता है, जब तक पाइपलाइन पूरी तरह से बंद नहीं हो जाती. हर फ़्रेम को अब भी वापस भेजना होगा. स्ट्रीम का आखिरी फ़्रेम डिलीवर होने के बाद, एक NULL bufferHandle डिलीवर किया जाएगा. इससे पता चलेगा कि स्ट्रीम खत्म हो गई है और अब कोई फ़्रेम डिलीवर नहीं किया जाएगा. NULL
bufferHandle को doneWithFrame()
के ज़रिए वापस भेजने की ज़रूरत नहीं है. हालांकि, अन्य सभी हैंडल वापस भेजे जाने चाहिए
तकनीकी तौर पर, मालिकाना हक वाले बफ़र फ़ॉर्मैट का इस्तेमाल किया जा सकता है. हालांकि, कंपैटिबिलिटी की जांच के लिए, बफ़र को इन चार फ़ॉर्मैट में से किसी एक में होना चाहिए: NV21 (YCrCb 4:2:0 Semi-Planar), YV12 (YCrCb 4:2:0 Planar), YUYV (YCrCb 4:2:2 Interleaved), RGBA (32 bit R:G:B:x), BGRA (32 bit B:G:R:x). चुना गया फ़ॉर्मैट, प्लैटफ़ॉर्म के GLES पर लागू होने वाले GL टेक्सचर का मान्य सोर्स होना चाहिए.
ऐप्लिकेशन को BufferDesc
स्ट्रक्चर में, bufferId
फ़ील्ड और memHandle
के बीच किसी भी तरह के पत्राचार पर भरोसा नहीं करना चाहिए. bufferId
वैल्यू, HAL ड्राइवर के लिए निजी होती हैं. साथ ही, HAL ड्राइवर अपनी ज़रूरत के हिसाब से इनका इस्तेमाल कर सकता है.
IEvsDisplay
यह ऑब्जेक्ट, Evs डिसप्ले को दिखाता है. साथ ही, डिसप्ले की स्थिति को कंट्रोल करता है और इमेज को दिखाने का काम करता है.
getDisplayInfo() generates (DisplayDesc info);
सिस्टम की ओर से उपलब्ध कराए गए ईवीएस डिसप्ले के बारे में बुनियादी जानकारी दिखाता है. इसके लिए, DisplayDesc देखें.
setDisplayState(DisplayState state) generates (EvsResult result);
यह कुकी, डिसप्ले की स्थिति सेट करती है. क्लाइंट, डिसप्ले की स्थिति को सेट करके अपनी ज़रूरत के हिसाब से स्थिति तय कर सकते हैं. साथ ही, एचएएल को किसी भी स्थिति में, किसी भी स्थिति के लिए किए गए अनुरोध को स्वीकार करना होगा. हालांकि, ऐसा हो सकता है कि अनुरोध को अनदेखा कर दिया जाए.
शुरू होने पर, डिसप्ले को NOT_VISIBLE
स्थिति में शुरू होने के लिए तय किया जाता है. इसके बाद, क्लाइंट से VISIBLE_ON_NEXT_FRAME
स्थिति का अनुरोध करने और वीडियो उपलब्ध कराने के लिए कहा जाता है. जब डिसप्ले की ज़रूरत नहीं होती है, तब क्लाइंट से उम्मीद की जाती है कि वह आखिरी वीडियो फ़्रेम पास करने के बाद, NOT_VISIBLE
स्थिति का अनुरोध करे.
इसे किसी भी राज्य के लिए, किसी भी समय अनुरोध किया जा सकता है. अगर डिसप्ले पहले से ही दिख रहा है, तो VISIBLE_ON_NEXT_FRAME
पर सेट होने पर भी वह दिखना चाहिए. अनुरोध की गई स्थिति, ऐसी enum वैल्यू नहीं है जिसकी पहचान नहीं की जा सकी है. इस स्थिति में, हमेशा OK दिखता है. अगर अनुरोध की गई स्थिति, ऐसी enum वैल्यू है जिसकी पहचान नहीं की जा सकी है, तो INVALID_ARG
दिखता है.
getDisplayState() generates (DisplayState state);
डिसप्ले की स्थिति का पता लगाता है. HAL को मौजूदा स्थिति की जानकारी देनी चाहिए. यह जानकारी, हाल ही में अनुरोध की गई स्थिति से अलग हो सकती है. डिस्प्ले की स्थितियों को बदलने के लिए ज़िम्मेदार लॉजिक, डिवाइस लेयर के ऊपर होना चाहिए. इससे HAL को डिस्प्ले की स्थितियों को अपने-आप बदलने से रोका जा सकेगा.
getTargetBuffer() generates (handle bufferHandle);
यह डिसप्ले से जुड़े फ़्रेम बफ़र का हैंडल दिखाता है. इस बफ़र को लॉक किया जा सकता है. साथ ही, सॉफ़्टवेयर और/या GL इसे लिख सकते हैं. इस बफ़र को returnTargetBufferForDisplay()
को कॉल करके वापस भेजना होगा. भले ही, डिसप्ले अब न दिख रहा हो.
तकनीकी तौर पर, मालिकाना हक वाले बफ़र फ़ॉर्मैट का इस्तेमाल किया जा सकता है. हालांकि, कंपैटिबिलिटी की जांच के लिए, बफ़र को इन चार फ़ॉर्मैट में से किसी एक में होना चाहिए: NV21 (YCrCb 4:2:0 सेमी-प्लानर), YV12 (YCrCb 4:2:0 प्लानर), YUYV (YCrCb 4:2:2 इंटरलीव्ड), RGBA (32 बिट R:G:B:x), BGRA (32 बिट B:G:R:x). चुना गया फ़ॉर्मैट, प्लैटफ़ॉर्म के GLES पर लागू होने वाला मान्य GL रेंडर टारगेट होना चाहिए.
गड़बड़ी होने पर, शून्य हैंडल वाला बफ़र वापस कर दिया जाता है. हालांकि, ऐसे बफ़र को returnTargetBufferForDisplay
को वापस भेजने की ज़रूरत नहीं होती.
returnTargetBufferForDisplay(handle bufferHandle) generates (EvsResult result);
यह डिसप्ले को बताता है कि बफ़र, डिसप्ले के लिए तैयार है. getTargetBuffer()
को कॉल करके सिर्फ़ उन बफ़र को वापस पाया जा सकता है जिनका इस्तेमाल इस कॉल के लिए किया जा सकता है. साथ ही, क्लाइंट ऐप्लिकेशन, getTargetBuffer()
के कॉन्टेंट में बदलाव नहीं कर सकता. इस कॉल के बाद, क्लाइंट के लिए बफ़र का इस्तेमाल नहीं किया जा सकता.BufferDesc
अगर अनुरोध पूरा हो जाता है, तो OK दिखाता है. अगर अनुरोध पूरा नहीं होता है, तो गड़बड़ी का कोड दिखाता है. इसमें INVALID_ARG
या BUFFER_NOT_AVAILABLE
शामिल हो सकता है.
struct DisplayDesc { string display_id; int32 vendor_flags; // Opaque value }
यह EVS डिसप्ले की बुनियादी प्रॉपर्टी के बारे में बताता है. साथ ही, EVS को लागू करने के लिए इसकी ज़रूरत होती है. ईवीएस डिसप्ले के बारे में बताने के लिए, HAL इस स्ट्रक्चर को भरने के लिए ज़िम्मेदार होता है. यह कोई फ़िज़िकल डिसप्ले या वर्चुअल डिसप्ले हो सकता है. इसे किसी दूसरे प्रज़ेंटेशन डिवाइस के साथ ओवरले या मिक्स किया जाता है.
display_id
. यह एक स्ट्रिंग होती है, जो डिसप्ले की खास तौर पर पहचान करती है. यह डिवाइस का कर्नल डिवाइस नेम या डिवाइस का नाम हो सकता है. जैसे, rearview. इस स्ट्रिंग की वैल्यू, HAL लागू करने वाला सॉफ़्टवेयर चुनता है. साथ ही, इसका इस्तेमाल ऊपर मौजूद स्टैक करता है.vendor_flags
. यह ड्राइवर से कस्टम ईवीएस ऐप्लिकेशन तक, खास कैमरा जानकारी को ओपेक तरीके से पास करने का एक तरीका है. इसे ड्राइवर से ईवीएस ऐप्लिकेशन तक बिना किसी बदलाव के पास किया जाता है. ईवीएस ऐप्लिकेशन के पास इसे अनदेखा करने का विकल्प होता है.
enum DisplayState : uint32 { NOT_OPEN, // Display has not been “opened” yet NOT_VISIBLE, // Display is inhibited VISIBLE_ON_NEXT_FRAME, // Will become visible with next frame VISIBLE, // Display is currently active DEAD, // Display is not available. Interface should be closed }
इससे ईवीएस डिसप्ले की स्थिति के बारे में पता चलता है. यह बंद (ड्राइवर को नहीं दिखता) या चालू (ड्राइवर को इमेज दिखती है) हो सकता है.
इसमें एक ट्रांज़िएंट स्टेट शामिल होती है. इसमें डिसप्ले अभी तक नहीं दिखता है, लेकिन returnTargetBufferForDisplay()
कॉल के ज़रिए इमेज के अगले फ़्रेम की डिलीवरी होने पर दिखने के लिए तैयार होता है.
EVS Manager
ईवीएस मैनेजर, ईवीएस सिस्टम के लिए सार्वजनिक इंटरफ़ेस उपलब्ध कराता है. इससे बाहरी कैमरे के व्यू इकट्ठा किए जा सकते हैं और उन्हें दिखाया जा सकता है. जहां हार्डवेयर ड्राइवर, हर संसाधन (कैमरा या डिसप्ले) के लिए सिर्फ़ एक चालू इंटरफ़ेस की अनुमति देते हैं वहां EVS Manager, कैमरों के लिए शेयर किए गए ऐक्सेस की सुविधा देता है. एक प्राइमरी EVS ऐप्लिकेशन, EVS Manager का पहला क्लाइंट होता है. साथ ही, यह डिसप्ले डेटा लिखने की अनुमति पाने वाला एकमात्र क्लाइंट होता है. अन्य क्लाइंट को कैमरे की इमेज का रीड-ओनली ऐक्सेस दिया जा सकता है.
EVS मैनेजर, HAL ड्राइवर के तौर पर काम करने वाले एपीआई को लागू करता है. साथ ही, एक साथ कई क्लाइंट को सेवा देता है. इसका मतलब है कि एक से ज़्यादा क्लाइंट, EVS मैनेजर के ज़रिए कैमरा खोल सकते हैं और वीडियो स्ट्रीम पा सकते हैं.

दूसरी इमेज. EVS Manager, EVS Hardware API की तरह ही काम करता है.
EVS Hardware HAL या EVS Manager API के ज़रिए काम करने पर, ऐप्लिकेशन को कोई अंतर नहीं दिखता. हालांकि, EVS Manager API से एक साथ कई कैमरा स्ट्रीम ऐक्सेस की जा सकती हैं. ईवीएस मैनेजर, ईवीएस हार्डवेयर एचएएल लेयर का एक ऐसा क्लाइंट है जिसे अनुमति मिली हुई है. साथ ही, यह ईवीएस हार्डवेयर एचएएल के लिए प्रॉक्सी के तौर पर काम करता है.
यहां दिए गए सेक्शन में सिर्फ़ उन कॉल के बारे में बताया गया है जिनका EVS Manager को लागू करने के दौरान अलग (बढ़ा हुआ) व्यवहार होता है. बाकी कॉल, EVS HAL के ब्यौरे के जैसे ही होते हैं.
IEvsEnumerator
openCamera(string camera_id) generates (IEvsCamera camera);
यह फ़ंक्शन, एक इंटरफ़ेस ऑब्जेक्ट हासिल करता है. इसका इस्तेमाल, किसी खास कैमरे से इंटरैक्ट करने के लिए किया जाता है. इस कैमरे की पहचान, यूनीक camera_id स्ट्रिंग से होती है. अगर फ़ंक्शन काम नहीं करता है, तो यह NULL दिखाता है.
ईवीएस मैनेजर लेयर पर, जब तक सिस्टम के ज़रूरी संसाधन उपलब्ध हैं, तब तक पहले से खुले हुए कैमरे को किसी दूसरी प्रोसेस से फिर से खोला जा सकता है. इससे वीडियो स्ट्रीम को कई उपभोक्ता ऐप्लिकेशन पर टी किया जा सकता है. ईवीएस मैनेजर लेयर पर मौजूद camera_id
स्ट्रिंग, ईवीएस हार्डवेयर लेयर को रिपोर्ट की गई स्ट्रिंग के जैसी ही होती हैं.
IEvsCamera
EVS Manager, IEvsCamera को लागू करने की सुविधा देता है. इसे इंटरनल तौर पर वर्चुअलाइज़ किया जाता है, ताकि एक क्लाइंट के कैमरे पर किए गए ऑपरेशन से दूसरे क्लाइंट पर असर न पड़े. इससे क्लाइंट को अपने कैमरों का ऐक्सेस मिलता है.
startVideoStream(IEvsCameraStream receiver) generates (EvsResult result);
वीडियो स्ट्रीम शुरू करता है. क्लाइंट, एक ही कैमरे पर वीडियो स्ट्रीम को अलग-अलग तरीके से शुरू और बंद कर सकते हैं. पहला क्लाइंट शुरू होने पर, कैमरा चालू हो जाता है.
doneWithFrame(uint32 frameId, handle bufferHandle) generates (EvsResult result);
यह फ़्रेम दिखाता है. हर क्लाइंट को फ़्रेम का इस्तेमाल करने के बाद उन्हें वापस करना होगा. हालांकि, वे फ़्रेम को तब तक अपने पास रख सकते हैं, जब तक वे चाहें. जब किसी क्लाइंट के पास मौजूद फ़्रेम की संख्या, कॉन्फ़िगर की गई सीमा तक पहुंच जाती है, तो उसे तब तक कोई और फ़्रेम नहीं मिलेगा, जब तक वह एक फ़्रेम वापस नहीं भेज देता. फ़्रेम स्किप करने की इस समस्या का असर अन्य क्लाइंट पर नहीं पड़ता. उन्हें सभी फ़्रेम पहले की तरह मिलते रहते हैं.
stopVideoStream();
वीडियो स्ट्रीम को बंद करता है. हर क्लाइंट, किसी भी समय अपनी वीडियो स्ट्रीम बंद कर सकता है. इससे दूसरे क्लाइंट पर कोई असर नहीं पड़ेगा. जब किसी कैमरे का आखिरी क्लाइंट, स्ट्रीम करना बंद कर देता है, तब हार्डवेयर लेयर पर मौजूद कैमरे की स्ट्रीम बंद हो जाती है.
setExtendedInfo(int32 opaqueIdentifier, int32 opaqueValue) generates (EvsResult result);
यह कुकी, ड्राइवर के हिसाब से वैल्यू भेजती है. इससे एक क्लाइंट, दूसरे क्लाइंट पर असर डाल सकता है. ईवीएस मैनेजर, वेंडर के तय किए गए कंट्रोल शब्दों के असर को नहीं समझ सकता. इसलिए, उन्हें वर्चुअलाइज़ नहीं किया जाता है. साथ ही, किसी कैमरे के सभी क्लाइंट पर साइड इफ़ेक्ट लागू होते हैं. उदाहरण के लिए, अगर किसी वेंडर ने फ़्रेम रेट बदलने के लिए इस कॉल का इस्तेमाल किया है, तो हार्डवेयर लेयर वाले कैमरे के सभी क्लाइंट को नए रेट पर फ़्रेम मिलेंगे.
IEvsDisplay
डिसप्ले का सिर्फ़ एक मालिक हो सकता है. भले ही, वह ईवीएस मैनेजर लेवल पर हो. Manager कोई सुविधा नहीं जोड़ता है. यह सिर्फ़ IEvsDisplay इंटरफ़ेस को सीधे तौर पर HAL के लागू करने वाले हिस्से तक पहुंचाता है.
ईवीएस ऐप्लिकेशन
Android में, ईवीएस ऐप्लिकेशन का नेटिव C++ रेफ़रंस इंप्लीमेंटेशन शामिल होता है. यह ईवीएस मैनेजर और वाहन के एचएएल से कम्यूनिकेट करता है, ताकि पीछे के कैमरे के बुनियादी फ़ंक्शन उपलब्ध कराए जा सकें. इस ऐप्लिकेशन को सिस्टम बूट प्रोसेस की शुरुआत में ही चालू हो जाना चाहिए. साथ ही, उपलब्ध कैमरों और कार की स्थिति (गियर और टर्न सिग्नल की स्थिति) के हिसाब से वीडियो दिखना चाहिए. ओईएम, ईवीएस ऐप्लिकेशन में बदलाव कर सकते हैं या उसे बदल सकते हैं. इसके लिए, वे वाहन के हिसाब से लॉजिक और प्रज़ेंटेशन का इस्तेमाल कर सकते हैं.

तीसरी इमेज. ईवीएस ऐप्लिकेशन का सैंपल लॉजिक, कैमरे की सूची पाएं.

चौथी इमेज. ईवीएस ऐप्लिकेशन का सैंपल लॉजिक, फ़्रेम कॉलबैक पाएं.
इमेज डेटा को ऐप्लिकेशन में स्टैंडर्ड ग्राफ़िक्स बफ़र के तौर पर दिखाया जाता है. इसलिए, इमेज को सोर्स बफ़र से आउटपुट बफ़र में ले जाने की ज़िम्मेदारी ऐप्लिकेशन की होती है. इससे डेटा कॉपी करने की लागत बढ़ जाती है. हालांकि, इससे ऐप्लिकेशन को यह मौका भी मिलता है कि वह इमेज को अपनी पसंद के हिसाब से डिसप्ले बफ़र में रेंडर कर सके.
उदाहरण के लिए, ऐप्लिकेशन पिक्सल डेटा को खुद ही ट्रांसफ़र कर सकता है. ऐसा हो सकता है कि वह डेटा को इनलाइन स्केल या रोटेशन ऑपरेशन के साथ ट्रांसफ़र करे. ऐप्लिकेशन, सोर्स इमेज को OpenGL टेक्सचर के तौर पर भी इस्तेमाल कर सकता है. साथ ही, आउटपुट बफ़र में जटिल सीन रेंडर कर सकता है. इसमें वर्चुअल एलिमेंट शामिल होते हैं, जैसे कि आइकॉन, दिशा-निर्देश, और ऐनिमेशन. ज़्यादा बेहतर ऐप्लिकेशन, एक साथ कई इनपुट कैमरों को भी चुन सकता है और उन्हें एक ही आउटपुट फ़्रेम में मर्ज कर सकता है. जैसे, वाहन के आस-पास के टॉप-डाउन, वर्चुअल व्यू में इस्तेमाल करने के लिए.
ईवीएस डिसप्ले HAL में EGL/SurfaceFlinger का इस्तेमाल करना
इस सेक्शन में, Android 10 में EVS Display HAL को लागू करने के लिए, EGL का इस्तेमाल करने का तरीका बताया गया है.
EVS HAL के रेफ़रंस इंप्लीमेंटेशन में, स्क्रीन पर कैमरे की झलक दिखाने के लिए EGL का इस्तेमाल किया जाता है. साथ ही, टारगेट EGL रेंडर सरफेस बनाने के लिए libgui
का इस्तेमाल किया जाता है. Android 8 और इसके बाद के वर्शन में, libgui
को VNDK-private के तौर पर क्लासिफ़ाई किया गया है. इसका मतलब है कि यह लाइब्रेरी, वीएनडीके लाइब्रेरी के लिए उपलब्ध है. हालांकि, वेंडर प्रोसेस इसका इस्तेमाल नहीं कर सकतीं.
एचएएल को वेंडर पार्टिशन में मौजूद होना चाहिए. इसलिए, वेंडर एचएएल में Surface का इस्तेमाल नहीं कर सकते.
वेंडर प्रोसेस के लिए libgui बनाना
EVS Display HAL को लागू करने के लिए, EGL/SurfaceFlinger का इस्तेमाल करने का सिर्फ़ एक तरीका है: libgui
का इस्तेमाल करना. libgui
को लागू करने का सबसे आसान तरीका यह है कि इसे सीधे तौर पर frameworks/native/libs/gui के ज़रिए लागू किया जाए. इसके लिए, बिल्ड स्क्रिप्ट में एक अतिरिक्त बिल्ड टारगेट का इस्तेमाल करें. यह टारगेट, libgui
टारगेट के बिलकुल जैसा है. हालांकि, इसमें दो फ़ील्ड जोड़े गए हैं:
name
vendor_available
cc_library_shared { name: "libgui_vendor", vendor_available: true, vndk: { enabled: false, }, double_loadable: true,
defaults: ["libgui_bufferqueue-defaults"],
srcs: [ … // bufferhub is not used when building libgui for vendors target: { vendor: { cflags: [ "-DNO_BUFFERHUB", "-DNO_INPUT", ], …
ध्यान दें: वेंडर टारगेट, NO_INPUT
मैक्रो का इस्तेमाल करके बनाए जाते हैं. यह पार्सल डेटा से 32-बिट का एक शब्द हटा देता है. SurfaceFlinger को इस फ़ील्ड की ज़रूरत होती है, लेकिन इसे हटा दिया गया है. इसलिए, SurfaceFlinger पार्सल को पार्स नहीं कर पाता. इसे fcntl
के तौर पर देखा जाता है:
W Parcel : Attempt to read object from Parcel 0x78d9cffad8 at offset 428 that is not in the object list E Parcel : fcntl(F_DUPFD_CLOEXEC) failed in Parcel::read, i is 0, fds[i] is 0, fd_count is 20, error: Unknown error 2147483647 W Parcel : Attempt to read object from Parcel 0x78d9cffad8 at offset 544 that is not in the object list
इस समस्या को हल करने के लिए:
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 6066421fa..25cf5f0ce 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -54,6 +54,9 @@ status_t layer_state_t::write(Parcel& output) const output.writeFloat(color.b); #ifndef NO_INPUT inputInfo.write(output); +#else + // Write a dummy 32-bit word. + output.writeInt32(0); #endif output.write(transparentRegion); output.writeUint32(transform);
बनाने के निर्देशों का सैंपल यहाँ दिया गया है. आपको $(ANDROID_PRODUCT_OUT)/system/lib64/libgui_vendor.so
मिलेगा.
$ cd <your_android_source_tree_top> $ . ./build/envsetup. $ lunch <product_name>-<build_variant> ============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=10 TARGET_PRODUCT=<product_name> TARGET_BUILD_VARIANT=<build_variant> TARGET_BUILD_TYPE=release TARGET_ARCH=arm64 TARGET_ARCH_VARIANT=armv8-a TARGET_CPU_VARIANT=generic TARGET_2ND_ARCH=arm TARGET_2ND_ARCH_VARIANT=armv7-a-neon TARGET_2ND_CPU_VARIANT=cortex-a9 HOST_ARCH=x86_64 HOST_2ND_ARCH=x86 HOST_OS=linux HOST_OS_EXTRA=<host_linux_version> HOST_CROSS_OS=windows HOST_CROSS_ARCH=x86 HOST_CROSS_2ND_ARCH=x86_64 HOST_BUILD_TYPE=release BUILD_ID=QT OUT_DIR=out ============================================
$ m -j libgui_vendor … $ find $ANDROID_PRODUCT_OUT/system -name "libgui_vendor*" .../out/target/product/hawk/system/lib64/libgui_vendor.so .../out/target/product/hawk/system/lib/libgui_vendor.so
ईवीएस एचएएल को लागू करने के लिए बाइंडर का इस्तेमाल करना
Android 8 और इसके बाद के वर्शन में, /dev/binder
डिवाइस नोड सिर्फ़ फ़्रेमवर्क प्रोसेस के लिए उपलब्ध है. इसलिए, वेंडर प्रोसेस के लिए यह उपलब्ध नहीं है. इसके बजाय, वेंडर प्रोसेस को /dev/hwbinder
का इस्तेमाल करना चाहिए. साथ ही, सभी एआईडीएल इंटरफ़ेस को एचआईडीएल में बदलना चाहिए. अगर आपको वेंडर प्रोसेस के बीच एआईडीएल इंटरफ़ेस का इस्तेमाल जारी रखना है, तो बाइंडर डोमेन, /dev/vndbinder
का इस्तेमाल करें.
आईपीसी डोमेन | ब्यौरा |
---|---|
/dev/binder |
एआईडीएल इंटरफ़ेस की मदद से, फ़्रेमवर्क/ऐप्लिकेशन प्रोसेस के बीच आईपीसी |
/dev/hwbinder |
एचआईडीएल इंटरफ़ेस के साथ फ़्रेमवर्क/वेंडर प्रोसेस के बीच आईपीसी एचआईडीएल इंटरफ़ेस के साथ वेंडर प्रोसेस के बीच आईपीसी |
/dev/vndbinder |
AIDL इंटरफ़ेस के साथ वेंडर/वेंडर प्रोसेस के बीच आईपीसी |
SurfaceFlinger, एआईडीएल इंटरफ़ेस तय करता है. हालांकि, वेंडर प्रोसेस सिर्फ़ एचआईडीएल इंटरफ़ेस का इस्तेमाल करके, फ़्रेमवर्क प्रोसेस के साथ कम्यूनिकेट कर सकती हैं. मौजूदा एआईडीएल इंटरफ़ेस को एचआईडीएल में बदलने के लिए, काफ़ी काम करना पड़ता है. हालांकि, Android में एक ऐसा तरीका उपलब्ध है जिसकी मदद से, libbinder
के लिए बाइंडर ड्राइवर चुना जा सकता है. इससे यूज़रस्पेस लाइब्रेरी प्रोसेस लिंक होती हैं.
diff --git a/evs/sampleDriver/service.cpp b/evs/sampleDriver/service.cpp index d8fb3166..5fd02935 100644 --- a/evs/sampleDriver/service.cpp +++ b/evs/sampleDriver/service.cpp @@ -21,6 +21,7 @@ #include <utils/Errors.h> #include <utils/StrongPointer.h> #include <utils/Log.h> +#include <binder/ProcessState.h> #include "ServiceNames.h" #include "EvsEnumerator.h" @@ -43,6 +44,9 @@ using namespace android; int main() { ALOGI("EVS Hardware Enumerator service is starting"); + // Use /dev/binder for SurfaceFlinger + ProcessState::initWithDriver("/dev/binder"); + // Start a thread to listen to video device addition events. std::atomic<bool> running { true }; std::thread ueventHandler(EvsEnumerator::EvsUeventThread, std::ref(running));
ध्यान दें: वेंडर प्रोसेस को Process
या IPCThreadState
को कॉल करने से पहले या कोई भी बाइंडर कॉल करने से पहले, इस फ़ंक्शन को कॉल करना चाहिए.
SELinux की नीतियां
अगर डिवाइस में Treble को पूरी तरह से लागू किया गया है, तो SELinux, वेंडर प्रोसेस को /dev/binder
का इस्तेमाल करने से रोकता है. उदाहरण के लिए, EVS HAL के सैंपल को hal_evs_driver
डोमेन असाइन किया गया है. इसके लिए, binder_device
डोमेन में पढ़ने/लिखने की अनुमतियां ज़रूरी हैं.
W ProcessState: Opening '/dev/binder' failed: Permission denied F ProcessState: Binder driver could not be opened. Terminating. F libc : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 9145 (android.hardwar), pid 9145 (android.hardwar) W android.hardwar: type=1400 audit(0.0:974): avc: denied { read write } for name="binder" dev="tmpfs" ino=2208 scontext=u:r:hal_evs_driver:s0 tcontext=u:object_r:binder_device:s0 tclass=chr_file permissive=0
हालांकि, इन अनुमतियों को जोड़ने से बिल्ड फ़ेल हो जाता है, क्योंकि यह system/sepolicy/domain.te
में फ़ुल-ट्रेबल डिवाइस के लिए तय किए गए, कभी भी अनुमति न देने से जुड़े इन नियमों का उल्लंघन करता है.
libsepol.report_failure: neverallow on line 631 of system/sepolicy/public/domain.te (or line 12436 of policy.conf) violated by allow hal_evs_driver binder_device:chr_file { read write }; libsepol.check_assertions: 1 neverallow failures occurred
full_treble_only(` neverallow { domain -coredomain -appdomain -binder_in_vendor_violators } binder_device:chr_file rw_file_perms; ')
binder_in_vendor_violators
एक ऐसा एट्रिब्यूट है जो बग का पता लगाने और डेवलपमेंट में मदद करने के लिए दिया जाता है. इसका इस्तेमाल, Android 10 के लिए ऊपर बताई गई नीति के उल्लंघन को ठीक करने के लिए भी किया जा सकता है.
diff --git a/evs/sepolicy/evs_driver.te b/evs/sepolicy/evs_driver.te index f1f31e9fc..6ee67d88e 100644 --- a/evs/sepolicy/evs_driver.te +++ b/evs/sepolicy/evs_driver.te @@ -3,6 +3,9 @@ type hal_evs_driver, domain, coredomain; hal_server_domain(hal_evs_driver, hal_evs) hal_client_domain(hal_evs_driver, hal_evs) +# Allow to use /dev/binder +typeattribute hal_evs_driver binder_in_vendor_violators; + # allow init to launch processes in this context type hal_evs_driver_exec, exec_type, file_type, system_file_type; init_daemon_domain(hal_evs_driver)
वेंडर प्रोसेस के तौर पर, ईवीएस एचएएल का रेफ़रंस इंप्लीमेंटेशन बनाना
रेफ़रंस के तौर पर, packages/services/Car/evs/Android.mk
में ये बदलाव किए जा सकते हैं. पुष्टि करें कि बताए गए सभी बदलाव, आपके लागू करने के तरीके के हिसाब से काम करते हैं.
diff --git a/evs/sampleDriver/Android.mk b/evs/sampleDriver/Android.mk index 734feea7d..0d257214d 100644 --- a/evs/sampleDriver/Android.mk +++ b/evs/sampleDriver/Android.mk @@ -16,7 +16,7 @@ LOCAL_SRC_FILES := \ LOCAL_SHARED_LIBRARIES := \ android.hardware.automotive.evs@1.0 \ libui \ - libgui \ + libgui_vendor \ libEGL \ libGLESv2 \ libbase \ @@ -33,6 +33,7 @@ LOCAL_SHARED_LIBRARIES := \ LOCAL_INIT_RC := android.hardware.automotive.evs@1.0-sample.rc LOCAL_MODULE := android.hardware.automotive.evs@1.0-sample +LOCAL_PROPRIETARY_MODULE := true LOCAL_MODULE_TAGS := optional LOCAL_STRIP_MODULE := keep_symbols @@ -40,6 +41,7 @@ LOCAL_STRIP_MODULE := keep_symbols LOCAL_CFLAGS += -DLOG_TAG=\"EvsSampleDriver\" LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES -DEGL_EGLEXT_PROTOTYPES LOCAL_CFLAGS += -Wall -Werror -Wunused -Wunreachable-code +LOCAL_CFLAGS += -Iframeworks/native/include # NOTE: It can be helpful, while debugging, to disable optimizations #LOCAL_CFLAGS += -O0 -g diff --git a/evs/sampleDriver/service.cpp b/evs/sampleDriver/service.cpp index d8fb31669..5fd029358 100644 --- a/evs/sampleDriver/service.cpp +++ b/evs/sampleDriver/service.cpp @@ -21,6 +21,7 @@ #include <utils/Errors.h> #include <utils/StrongPointer.h> #include <utils/Log.h> +#include <binder/ProcessState.h> #include "ServiceNames.h" #include "EvsEnumerator.h" @@ -43,6 +44,9 @@ using namespace android; int main() { ALOGI("EVS Hardware Enumerator service is starting"); + // Use /dev/binder for SurfaceFlinger + ProcessState::initWithDriver("/dev/binder"); + // Start a thread to listen video device addition events. std::atomic<bool> running { true }; std::thread ueventHandler(EvsEnumerator::EvsUeventThread, std::ref(running)); diff --git a/evs/sepolicy/evs_driver.te b/evs/sepolicy/evs_driver.te index f1f31e9fc..632fc7337 100644 --- a/evs/sepolicy/evs_driver.te +++ b/evs/sepolicy/evs_driver.te @@ -3,6 +3,9 @@ type hal_evs_driver, domain, coredomain; hal_server_domain(hal_evs_driver, hal_evs) hal_client_domain(hal_evs_driver, hal_evs) +# allow to use /dev/binder +typeattribute hal_evs_driver binder_in_vendor_violators; + # allow init to launch processes in this context type hal_evs_driver_exec, exec_type, file_type, system_file_type; init_daemon_domain(hal_evs_driver) @@ -22,3 +25,7 @@ allow hal_evs_driver ion_device:chr_file r_file_perms; # Allow the driver to access kobject uevents allow hal_evs_driver self:netlink_kobject_uevent_socket create_socket_perms_no_ioctl; + +# Allow the driver to use the binder device +allow hal_evs_driver binder_device:chr_file rw_file_perms;