Android 12 में, GKI 2.0, ION ऐलोकेटर को इन वजहों से डीएमए-बीयूएफ़ हीप से बदल देता है:
- सुरक्षा: हर DMA-BUF हेप एक अलग वर्ण डिवाइस होता है. इसलिए, हर हेप के ऐक्सेस को sepolicy की मदद से अलग से कंट्रोल किया जा सकता है. ION में ऐसा करना संभव नहीं था, क्योंकि किसी भी हेप से ऐलोकेशन करने के लिए, सिर्फ़
/dev/ion
डिवाइस का ऐक्सेस ज़रूरी था. - एबीआई (ऑब्जेक्ट फ़ाइल फ़ॉर्मैट) में बदलाव न होना: ION के मुकाबले, डीएमए-बफ़ हेप्स फ़्रेमवर्क का IOCTL इंटरफ़ेस, एबीआई में बदलाव न होने वाला होता है. इसकी वजह यह है कि इसे अपस्ट्रीम Linux कर्नेल में मैनेज किया जाता है.
- स्टैंडर्डाइज़ेशन: डीएमए-बीयूएफ़ हीप फ़्रेमवर्क, अच्छी तरह से तय किया गया यूएपीआई ऑफ़र करता है. ION में कस्टम फ़्लैग और हीप आईडी की अनुमति थी. इसकी वजह से, एक सामान्य टेस्टिंग फ़्रेमवर्क डेवलप नहीं किया जा सका, क्योंकि हर डिवाइस पर ION लागू करने का तरीका अलग-अलग हो सकता है.
Android Common Kernel की android12-5.10
शाखा 1 मार्च, 2021 को बंद कर दी गई है.CONFIG_ION
बैकग्राउंड
यहां ION और डीएमए-बीयूएफ़ हेप की तुलना की गई है.
ION और डीएमए-बीयूएफ़ हीप फ़्रेमवर्क के बीच समानताएं
- ION और डीएमए-बीयूएफ़ हीप फ़्रेमवर्क, दोनों ही हीप पर आधारित डीएमए-बीयूएफ़ एक्सपोर्टर हैं.
- दोनों ही, हर हेप को अपना एलोकेटर और डीएमए-बफ़ ऑपरेशन तय करने की सुविधा देते हैं.
- दोनों स्कीम की परफ़ॉर्मेंस एक जैसी होती है, क्योंकि दोनों को ऐलोकेशन के लिए एक ही IOCTL की ज़रूरत होती है.
ION और DMA-BUF हेप्स फ़्रेमवर्क के बीच अंतर
ION हीप | डीएमए-बीयूएफ़ हीप |
---|---|
सभी ION एलोकेशन, /dev/ion की मदद से किए जाते हैं.
|
हर डीएमए-बीयूएफ़ हीप एक वर्ण डिवाइस होता है, जो /dev/dma_heap/<heap_name> पर मौजूद होता है.
|
ION, हेप के निजी फ़्लैग के साथ काम करता है. | डीएमए-बीयूएफ़ हीप, हीप के निजी फ़्लैग के साथ काम नहीं करते. इसके बजाय, हर अलग तरह का
ऐलोकेशन, अलग हेप से किया जाता है. उदाहरण के लिए, कैश मेमोरी में सेव किए गए और
सेव नहीं किए गए सिस्टम हेप वैरिएंट, अलग-अलग हेप होते हैं. ये /dev/dma_heap/system और
/dev/dma_heap/system_uncached पर मौजूद होते हैं.
|
ऐलोकेशन के लिए, हेप आईडी/मास्क, और फ़्लैग की जानकारी देना ज़रूरी है. | हेप के नाम का इस्तेमाल, एलोकेशन के लिए किया जाता है. |
नीचे दिए गए सेक्शन में, ION के साथ काम करने वाले कॉम्पोनेंट की सूची दी गई है. साथ ही, उन्हें DMA-BUF हेप्स फ़्रेमवर्क पर स्विच करने का तरीका भी बताया गया है.
ट्रांज़िशन कर्नेल ड्राइवर को ION से डीएमए-बीयूएफ़ हीप पर
ION हेप लागू करने वाले कर्नेल ड्राइवर
ION और डीएमए-बीयूएफ़, दोनों ही हीप में हर हीप के लिए, अपने ऐलोकेटर और डीएमए-बीयूएफ़ ऑपरेशन लागू करने की सुविधा होती है. इसलिए, हेप को रजिस्टर करने के लिए एपीआई के किसी दूसरे सेट का इस्तेमाल करके, ION हेप लागू करने से DMA-BUF हेप लागू करने पर स्विच किया जा सकता है. इस टेबल में, ION हीप रजिस्टरेशन एपीआई और उनके बराबर के डीएमए-बीयूएफ़ हीप एपीआई दिखाए गए हैं.
ION हीप | डीएमए-बीयूएफ़ हीप |
---|---|
void ion_device_add_heap(struct ion_heap *heap)
|
struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
|
void ion_device_remove_heap(struct ion_heap *heap)
|
void dma_heap_put(struct dma_heap *heap);
|
डीएमए-बीयूएफ़ हीप, हीप के निजी फ़्लैग के साथ काम नहीं करते. इसलिए, dma_heap_add()
एपीआई का इस्तेमाल करके, ढेर के हर वैरिएंट को अलग-अलग रजिस्टर करना होगा. कोड शेयर करने की सुविधा देने के लिए, हमारा सुझाव है कि एक ही ड्राइवर में एक ही हेप के सभी वैरिएंट रजिस्टर करें.
dma-buf: system_heap के इस उदाहरण में, सिस्टम के ढेर के कैश मेमोरी वाले और कैश मेमोरी के बिना वाले वैरिएंट को लागू करने का तरीका बताया गया है.
डीएमए-बीयूएफ़ हीप को शुरू से बनाने के लिए, इस dma-buf: heaps: example template का इस्तेमाल करें.
कर्नेल ड्राइवर, सीधे तौर पर ION हेप से एलोकेट कर रहे हैं
डीएमए-बीयूएफ़ हीप फ़्रेमवर्क, इन-कर्नल क्लाइंट के लिए ऐलोकेशन इंटरफ़ेस भी उपलब्ध कराता है. एलोकेशन का टाइप चुनने के लिए, हेप मास्क और फ़्लैग तय करने के बजाय, डीएमए-बफ़ हेप का इंटरफ़ेस, हेप के नाम को इनपुट के तौर पर लेता है.
यहां इन-कर्नल ION ऐलोकेशन एपीआई और इसके बराबर के डीएमए-बीयूएफ़ ढेर ऐलोकेशन एपीआई दिखाए गए हैं. हेप के मौजूद होने के बारे में क्वेरी करने के लिए, कर्नेल ड्राइवर dma_heap_find()
एपीआई का इस्तेमाल कर सकते हैं. एपीआई, struct dma_heap के किसी इंस्टेंस का पॉइंटर दिखाता है. इसे dma_heap_buffer_alloc()
एपीआई के लिए आर्ग्युमेंट के तौर पर पास किया जा सकता है.
ION हीप | डीएमए-बीयूएफ़ हीप |
---|---|
struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)
|
|
डीएमए-बीयूएफ़ का इस्तेमाल करने वाले कर्नेल ड्राइवर
सिर्फ़ डीएमए-बीयूएफ़ इंपोर्ट करने वाले ड्राइवर में कोई बदलाव करने की ज़रूरत नहीं है. ऐसा इसलिए है, क्योंकि ION हेप से ऐलोकेट किया गया बफ़र, ठीक उसी तरह काम करता है जिस तरह डीएमए-बीयूएफ़ हेप से ऐलोकेट किया गया बफ़र काम करता है.
ION के यूज़र-स्पेस क्लाइंट को डीएमए-बीयूएफ़ हीप पर ट्रांज़िशन करना
ION के यूज़र-स्पेस क्लाइंट के लिए ट्रांज़िशन को आसान बनाने के लिए, libdmabufheap
नाम की एक एब्स्ट्रैक्शन लाइब्रेरी उपलब्ध है. libdmabufheap
, डीएमए-बीयूएफ़ हीप और ION हीप में ऐलोकेशन की सुविधा देता है. यह पहले यह जांच करता है कि बताए गए नाम की DMA-BUF हेप मौजूद है या नहीं. अगर नहीं है, तो मिलती-जुलती ION हेप का इस्तेमाल किया जाता है.
क्लाइंट को /dev/ion using
ion_open()
खोलने के बजाय, अपने शुरू होने के दौरान BufferAllocator
ऑब्जेक्ट को शुरू करना चाहिए. ऐसा इसलिए होता है, क्योंकि /dev/ion
और /dev/dma_heap/<heap_name>
को खोलने से बने फ़ाइल डिस्क्रिप्टर को BufferAllocator
ऑब्जेक्ट मैनेज करता है.
libion
से libdmabufheap
पर स्विच करने के लिए, क्लाइंट के व्यवहार में इस तरह बदलाव करें:
- हेड आईडी/मास्क और हेप फ़्लैग के बजाय, हेप के नाम को ट्रैक करें, ताकि उसे ऐलोकेशन के लिए इस्तेमाल किया जा सके.
ion_alloc_fd()
एपीआई कोBufferAllocator::Alloc()
एपीआई से बदलें.ion_alloc_fd()
एपीआई, हेप मास्क और फ़्लैग आर्ग्युमेंट लेता है, जबकिBufferAllocator::Alloc()
एपीआई, हेप का नाम लेता है.
इस टेबल में इन बदलावों को दिखाया गया है. इसमें यह बताया गया है कि libion
और libdmabufheap
, कैश मेमोरी में सेव नहीं किए गए सिस्टम हेप को कैसे असाइन करते हैं.
ऐलोकेशन का टाइप | libion | libdmabufheap |
---|---|---|
सिस्टम हीप से कैश मेमोरी में ऐलोकेशन | ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, ION_FLAG_CACHED, &fd)
|
allocator->Alloc("system", size)
|
सिस्टम हीप से अनकैश किया गया ऐलोकेशन | ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, 0, &fd)
|
allocator->Alloc("system-uncached", size)
|
कैश मेमोरी में सेव नहीं किया गया सिस्टम हेप वैरिएंट, अपस्ट्रीम की अनुमति का इंतज़ार कर रहा है. हालांकि, यह पहले से ही android12-5.10
शाखा का हिस्सा है.
डिवाइसों को अपग्रेड करने के लिए, MapNameToIonHeap()
API किसी हेप के नाम को ION हेप पैरामीटर (हेप का नाम या मास्क और फ़्लैग) से मैप करने की अनुमति देता है, ताकि वे इंटरफ़ेस नाम के आधार पर एलोकेशन का इस्तेमाल कर सकें. यहां नाम के आधार पर ऐलोकेशन का उदाहरण दिया गया है.
libdmabufheap
के ज़रिए एक्सपोज़ किए गए हर एपीआई का दस्तावेज़ उपलब्ध है. लाइब्रेरी, C क्लाइंट के इस्तेमाल के लिए हेडर फ़ाइल भी दिखाती है.
Gralloc को लागू करने का रेफ़रंस
Hikey960 gralloc को लागू करने के लिए libdmabufheap
का इस्तेमाल किया जाता है. इसलिए, इसका इस्तेमाल लागू करने के लिए रेफ़रंस के तौर पर किया जा सकता है.
ueventd में जोड़ने के लिए ज़रूरी चीज़ें
डिवाइस के हिसाब से बनाई गई किसी भी नई DMA-BUF हेप के लिए, डिवाइस की ueventd.rc
फ़ाइल में एक नई एंट्री जोड़ें.
डीएमए-बीयूएफ़ हीप के साथ काम करने के लिए, ueventd को सेट अप करने के उदाहरण में बताया गया है कि डीएमए-बीयूएफ़ सिस्टम हीप के लिए, यह कैसे किया जाता है.
sepolicy में ज़रूरी बदलाव
उपयोगकर्ता स्पेस क्लाइंट को नए DMA-BUF ढेर को ऐक्सेस करने की अनुमति देने के लिए, sepolicy अनुमतियां जोड़ें. ज़रूरी अनुमतियां जोड़ने के इस उदाहरण में, डीएमए-बीयूएफ़ सिस्टम हीप को ऐक्सेस करने के लिए, अलग-अलग क्लाइंट के लिए बनाई गई sepolicy अनुमतियां दिखाई गई हैं.
फ़्रेमवर्क कोड से वेंडर हेप ऐक्सेस करना
Treble के नियमों का पालन करने के लिए, फ़्रेमवर्क कोड को सिर्फ़ वेंडर हेप की उन कैटगरी से ऐलोकेट किया जा सकता है जिन्हें पहले से मंज़ूरी मिल चुकी है.
पार्टनर से मिले सुझावों के आधार पर, Google ने वेंडर हेप की दो कैटगरी की पहचान की है. इन्हें फ़्रेमवर्क कोड से ऐक्सेस किया जाना चाहिए:
- सिस्टम हेप पर आधारित हेप, जिनमें डिवाइस या SoC के हिसाब से परफ़ॉर्मेंस को ऑप्टिमाइज़ करने की सुविधाएं होती हैं.
- सुरक्षित मेमोरी से एलोकेट किए जाने वाले हेप.
डिवाइस या SoC के हिसाब से परफ़ॉर्मेंस को ऑप्टिमाइज़ करने के लिए, सिस्टम हेप पर आधारित हेप
इस इस्तेमाल के उदाहरण के लिए, डिफ़ॉल्ट डीएमए-बीयूएफ़ हीप सिस्टम के हीप को लागू करने की सुविधा को बदला जा सकता है.
CONFIG_DMABUF_HEAPS_SYSTEM
कोgki_defconfig
में बंद किया गया है, ताकि इसे वेंडर मॉड्यूल बनाया जा सके.- VTS कंप्लायंस टेस्ट से यह पक्का होता है कि ढेर
/dev/dma_heap/system
पर मौजूद है. इन टेस्ट से यह भी पुष्टि की जाती है कि हेप को उपयोगकर्ता स्पेस से ऐलोकेट किया जा सकता है और रिटर्न किए गए फ़ाइल डिस्क्रिप्टर (fd
) को उपयोगकर्ता स्पेस से मेमोरी मैप (mmapped) किया जा सकता है.
ऊपर बताए गए पॉइंट, सिस्टम हेप के बिना कैश मेमोरी वाले वैरिएंट के लिए भी सही हैं. हालांकि, पूरी तरह से आईओ-कोहैरेंट डिवाइसों के लिए, इसका होना ज़रूरी नहीं है.
सुरक्षित मेमोरी से एलोकेट किए जाने वाले हेप
सुरक्षित हेप को लागू करने का तरीका, वेंडर के हिसाब से होना चाहिए. इसकी वजह यह है कि Android Common Kernel, सामान्य तौर पर सुरक्षित हेप को लागू करने की सुविधा के साथ काम नहीं करता.
- वेंडर के हिसाब से लागू किए गए टूल को
/dev/dma_heap/system-secure<vendor-suffix>
के तौर पर रजिस्टर करें. - हेप को लागू करना ज़रूरी नहीं है.
- अगर हेप मौजूद हैं, तो वीटीएस टेस्ट यह पक्का करते हैं कि उनसे एलोकेशन किया जा सकता है.
- फ़्रेमवर्क कॉम्पोनेंट को इन हेप का ऐक्सेस दिया जाता है, ताकि वे Codec2 HAL/बिना बाइंडर वाले, सेम-प्रोसेस एचएएल की मदद से हेप का इस्तेमाल शुरू कर सकें. हालांकि, Android फ़्रेमवर्क की सामान्य सुविधाएं, इन पर निर्भर नहीं हो सकतीं. ऐसा इसलिए है, क्योंकि इन सुविधाओं को लागू करने के तरीके में अंतर होता है. अगर आने वाले समय में, Android के सामान्य कर्नेल में सामान्य सुरक्षित हेप लागू किया जाता है, तो डिवाइसों को अपग्रेड करने से जुड़ी समस्याओं से बचने के लिए, उसे किसी दूसरे एबीआई का इस्तेमाल करना होगा.
डीएमए-बीयूएफ़ हीप के लिए कोडेक 2 ऐलोकेटर
AOSP में, डीएमए-बीयूएफ़ हीप इंटरफ़ेस के लिए codec2 ऐलोकेटर उपलब्ध है.
C2 डीएमए-बीयूएफ़ ढेर ऐलोकेटर के साथ, कॉम्पोनेंट स्टोर इंटरफ़ेस उपलब्ध है. इसकी मदद से, C2 एचएएल से ढेर पैरामीटर तय किए जा सकते हैं.
ION ढेर के लिए ट्रांज़िशन फ़्लो का सैंपल
ION से डीएमए-बीयूएफ़ हीप पर आसानी से स्विच करने के लिए, libdmabufheap
की मदद से एक हीप पर एक बार में स्विच किया जा सकता है. यहां दिए गए चरणों में, my_heap
नाम के ऐसे नॉन-लेगसी ION ढेर को ट्रांज़िशन करने के लिए सुझाया गया वर्कफ़्लो दिखाया गया है जो एक फ़्लैग, ION_FLAG_MY_FLAG
के साथ काम करता है.
पहला चरण: DMA-BUF फ़्रेमवर्क में ION हेप के बराबर का डेटा बनाएं. इस उदाहरण में, ION हीप my_heap
, फ़्लैग ION_FLAG_MY_FLAG
के साथ काम करती है. इसलिए, हम दो डीएमए-बीयूएफ़ हीप रजिस्टर करते हैं:
my_heap
का व्यवहार,ION_FLAG_MY_FLAG
फ़्लैग बंद होने पर ION ढेर के व्यवहार से पूरी तरह मेल खाता है.my_heap_special
का व्यवहार,ION_FLAG_MY_FLAG
फ़्लैग चालू होने पर ION ढेर के व्यवहार से पूरी तरह मेल खाता है.
दूसरा चरण: नई my_heap
और
my_heap_special
DMA-BUF हेप के लिए, ueventd में बदलाव करें. इस समय, हेप /dev/dma_heap/my_heap
और /dev/dma_heap/my_heap_special
के तौर पर दिखते हैं. साथ ही, इनमें ज़रूरी अनुमतियां भी होती हैं.
तीसरा चरण: my_heap
से एलोकेट करने वाले क्लाइंट के लिए, libdmabufheap
से लिंक करने के लिए उनके मेकफ़ाइल में बदलाव करें. क्लाइंट को शुरू करने के दौरान, BufferAllocator
ऑब्जेक्ट को इंस्टैंशिएट करें और MapNameToIonHeap()
एपीआई का इस्तेमाल करके, <ION heap name/mask, flag>
कॉम्बिनेशन को मिलते-जुलते DMA-BUF हेप नामों से मैप करें.
उदाहरण के लिए:
allocator->MapNameToIonHeap("my_heap_special" /* name of DMA-BUF heap */, "my_heap" /* name of the ION heap */, ION_FLAG_MY_FLAG /* ion flags */ )
नाम और फ़्लैग पैरामीटर के साथ MapNameToIonHeap()
एपीआई का इस्तेमाल करने के बजाय, <ION heap mask, flag>
से मिलते-जुलते DMA-BUF ढेर के नाम के लिए मैपिंग बनाई जा सकती है. इसके लिए, ION ढेर के नाम पैरामीटर को खाली पर सेट करें.
चौथा चरण: सही हेप के नाम का इस्तेमाल करके, ion_alloc_fd()
को BufferAllocator::Alloc()
से बदलें.
ऐलोकेशन टाइप | libion | libdmabufheap |
---|---|---|
my_heap से, ION_FLAG_MY_FLAG फ़्लैग के बिना ऐलोकेशन
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP, 0, &fd)
|
allocator->Alloc("my_heap", size)
|
my_heap से, ION_FLAG_MY_FLAG फ़्लैग के साथ ऐलोकेशन
|
ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP,
ION_FLAG_MY_FLAG, &fd)
|
allocator->Alloc("my_heap_special", size)
|
इस स्थिति में, क्लाइंट काम कर रहा है, लेकिन अब भी ION ढेर से जगह तय कर रहा है, क्योंकि उसके पास DMA-BUF ढेर खोलने के लिए ज़रूरी sepolicy अनुमतियां नहीं हैं.
पांचवां चरण: क्लाइंट के लिए, नई DMA-BUF हेप को ऐक्सेस करने के लिए ज़रूरी sepolicy अनुमतियां बनाएं. क्लाइंट अब नए डीएमए-बफ़ हेप से एलोकेट करने के लिए पूरी तरह से तैयार है.
छठा चरण: logcat की जांच करके पुष्टि करें कि एलोकेशन, नई डीएमए-बीयूएफ़ हीप से हो रहे हैं.
सातवां चरण: कर्नेल में ION ढेर my_heap
को बंद करें. अगर क्लाइंट कोड को अपग्रेड किए जा रहे डिवाइसों के साथ काम करने की ज़रूरत नहीं है (ऐसे डिवाइसों के कर्नेल में शायद सिर्फ़ ION ढेर काम करते हों), तो MapNameToIonHeap()
को भी हटाया जा सकता है.