অ্যান্ড্রয়েড ১২-এ, GKI 2.0 নিম্নলিখিত কারণগুলোর জন্য ION অ্যালোকেটরকে DMA-BUF হিপস দ্বারা প্রতিস্থাপন করে:
- নিরাপত্তা: যেহেতু প্রতিটি DMA-BUF হিপ একটি পৃথক ক্যারেক্টার ডিভাইস, তাই sepolicy ব্যবহার করে প্রতিটি হিপে প্রবেশাধিকার আলাদাভাবে নিয়ন্ত্রণ করা যায়। ION-এর ক্ষেত্রে এটি সম্ভব ছিল না, কারণ যেকোনো হিপ থেকে অ্যালোকেশনের জন্য শুধুমাত্র
/dev/ionডিভাইসে প্রবেশাধিকারের প্রয়োজন হতো। - ABI স্থিতিশীলতা: ION-এর বিপরীতে, DMA-BUF হিপস ফ্রেমওয়ার্কের IOCTL ইন্টারফেসটি ABI স্থিতিশীল, কারণ এটি আপস্ট্রিম লিনাক্স কার্নেলে রক্ষণাবেক্ষণ করা হয়।
- মানকীকরণ: DMA-BUF হিপস ফ্রেমওয়ার্ক একটি সুসংজ্ঞায়িত UAPI প্রদান করে। ION কাস্টম ফ্ল্যাগ এবং হিপ আইডি ব্যবহারের সুযোগ দিত, যা একটি সাধারণ টেস্টিং ফ্রেমওয়ার্ক তৈরিতে বাধা সৃষ্টি করত, কারণ প্রতিটি ডিভাইসের ION ইমপ্লিমেন্টেশন ভিন্নভাবে আচরণ করতে পারত।
অ্যান্ড্রয়েড কমন কার্নেলের android12-5.10 শাখাটি ১ মার্চ, ২০২১ তারিখে CONFIG_ION নিষ্ক্রিয় করে দিয়েছে।
পটভূমি
নিম্নে ION এবং DMA-BUF হিপগুলোর মধ্যে একটি সংক্ষিপ্ত তুলনা দেওয়া হলো।
ION এবং DMA-BUF হিপস ফ্রেমওয়ার্কের মধ্যে সাদৃশ্য
- ION এবং DMA-BUF হিপস ফ্রেমওয়ার্ক উভয়ই হিপ-ভিত্তিক DMA-BUF এক্সপোর্টার।
- তারা উভয়ই প্রতিটি হিপকে তার নিজস্ব অ্যালোকেটর এবং ডিএমএ-বিইউএফ অপস নির্ধারণ করার সুযোগ দেয়।
- বরাদ্দের কার্যকারিতা একই রকম, কারণ উভয় স্কিমের জন্যই বরাদ্দের জন্য একটিমাত্র IOCTL প্রয়োজন।
ION এবং DMA-BUF হিপস ফ্রেমওয়ার্কের মধ্যে পার্থক্য
| আয়ন স্তূপ | ডিএমএ-বিইউএফ হিপস |
|---|---|
সমস্ত ION অ্যালোকেশন /dev/ion দিয়ে করা হয়। | প্রতিটি DMA-BUF হিপ হলো একটি ক্যারেক্টার ডিভাইস যা /dev/dma_heap/<heap_name> -এ অবস্থিত। |
| ION হিপ প্রাইভেট ফ্ল্যাগ সমর্থন করে। | DMA-BUF হিপগুলো হিপ প্রাইভেট ফ্ল্যাগ সমর্থন করে না। এর পরিবর্তে, প্রতিটি ভিন্ন ধরনের অ্যালোকেশন একটি ভিন্ন হিপ থেকে করা হয়। উদাহরণস্বরূপ, ক্যাশড এবং আনক্যাশড সিস্টেম হিপ ভ্যারিয়েন্টগুলো হলো পৃথক হিপ, যা যথাক্রমে /dev/dma_heap/system এবং /dev/dma_heap/system_uncached এ অবস্থিত। |
| অ্যালোকেশনের জন্য হিপ আইডি/মাস্ক এবং ফ্ল্যাগ উল্লেখ করতে হবে। | অ্যালোকেশনের জন্য হিপ নেম ব্যবহার করা হয়। |
নিম্নলিখিত বিভাগগুলিতে ION-এর সাথে সম্পর্কিত উপাদানগুলির তালিকা দেওয়া হয়েছে এবং সেগুলিকে কীভাবে DMA-BUF হিপস ফ্রেমওয়ার্কে পরিবর্তন করতে হয় তা বর্ণনা করা হয়েছে।
কার্নেল ড্রাইভারগুলিকে ION থেকে DMA-BUF হিপে স্থানান্তর করুন
কার্নেল ড্রাইভার যা ION হিপস বাস্তবায়ন করে
ION এবং DMA-BUF উভয় হিপই প্রতিটি হিপকে তার নিজস্ব অ্যালোকেটর এবং DMA-BUF অপস প্রয়োগ করার সুযোগ দেয়। তাই, হিপটি রেজিস্টার করার জন্য ভিন্ন এক সেট এপিআই ব্যবহার করে আপনি একটি ION হিপ ইমপ্লিমেন্টেশন থেকে একটি DMA-BUF হিপ ইমপ্লিমেন্টেশনে পরিবর্তন করতে পারেন। এই সারণিতে ION হিপ রেজিস্ট্রেশন এপিআই এবং সেগুলোর সমতুল্য DMA-BUF হিপ এপিআইগুলো দেখানো হয়েছে।
| আয়ন স্তূপ | ডিএমএ-বিইউএফ হিপস |
|---|---|
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-BUF হিপগুলো হিপ প্রাইভেট ফ্ল্যাগ সমর্থন করে না। তাই হিপের প্রতিটি ভ্যারিয়েন্টকে অবশ্যই dma_heap_add() API ব্যবহার করে আলাদাভাবে রেজিস্টার করতে হবে। কোড শেয়ারিং সহজ করার জন্য, একই হিপের সমস্ত ভ্যারিয়েন্টকে একই ড্রাইভারের মধ্যে রেজিস্টার করার পরামর্শ দেওয়া হয়। এই dma-buf: system_heap উদাহরণটি সিস্টেম হিপের ক্যাশড এবং আনক্যাশড ভ্যারিয়েন্টগুলোর ইমপ্লিমেন্টেশন দেখায়।
প্রথম থেকে একটি DMA-BUF হিপ তৈরি করতে এই dma-buf: heaps: example টেমপ্লেটটি ব্যবহার করুন।
কার্নেল ড্রাইভারগুলি সরাসরি ION হিপ থেকে মেমরি বরাদ্দ করে
DMA-BUF হিপস ফ্রেমওয়ার্কটি ইন-কার্নেল ক্লায়েন্টদের জন্য একটি অ্যালোকেশন ইন্টারফেসও প্রদান করে। অ্যালোকেশনের ধরন নির্বাচন করার জন্য হিপ মাস্ক এবং ফ্ল্যাগ নির্দিষ্ট করার পরিবর্তে, DMA-BUF হিপস দ্বারা প্রদত্ত ইন্টারফেসটি ইনপুট হিসাবে একটি হিপের নাম গ্রহণ করে।
নিম্নলিখিত অংশে ইন-কার্নেল ION অ্যালোকেশন API এবং এর সমতুল্য DMA-BUF হিপ অ্যালোকেশন API দেখানো হয়েছে। কার্নেল ড্রাইভারগুলো কোনো হিপের অস্তিত্ব জানতে dma_heap_find() API ব্যবহার করতে পারে। এই API-টি struct dma_heap- এর একটি ইনস্ট্যান্সের পয়েন্টার রিটার্ন করে, যা পরবর্তীতে dma_heap_buffer_alloc() API-তে আর্গুমেন্ট হিসেবে পাস করা যায়।
| আয়ন স্তূপ | ডিএমএ-বিইউএফ হিপস |
|---|---|
struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags) | |
কার্নেল ড্রাইভার যা DMA-BUF ব্যবহার করে
যেসব ড্রাইভার শুধুমাত্র DMA-BUF ইম্পোর্ট করে, তাদের কোনো পরিবর্তনের প্রয়োজন নেই, কারণ একটি ION হিপ থেকে বরাদ্দ করা বাফার, একটি সমতুল্য DMA-BUF হিপ থেকে বরাদ্দ করা বাফারের মতোই হুবহু একই আচরণ করে।
ION-এর ইউজার-স্পেস ক্লায়েন্টদের DMA-BUF হিপে স্থানান্তর করুন
ION-এর ইউজার-স্পেস ক্লায়েন্টদের জন্য এই রূপান্তর সহজ করতে libdmabufheap নামক একটি অ্যাবস্ট্রাকশন লাইব্রেরি উপলব্ধ আছে। libdmabufheap , DMA-BUF হিপ এবং ION হিপ উভয়টিতেই মেমরি বরাদ্দ সমর্থন করে। এটি প্রথমে পরীক্ষা করে দেখে যে নির্দিষ্ট নামের কোনো DMA-BUF হিপ বিদ্যমান আছে কিনা এবং যদি না থাকে, তবে একটি সমতুল্য ION হিপ থাকলে সেটিতে ফিরে যায়।
ক্লায়েন্টদের তাদের ইনিশিয়ালাইজেশনের সময় /dev/ion using ion_open() খোলার পরিবর্তে একটি BufferAllocator অবজেক্ট ইনিশিয়ালাইজ করা উচিত। এর কারণ হলো /dev/ion এবং /dev/dma_heap/<heap_name> খোলার মাধ্যমে তৈরি হওয়া ফাইল ডেসক্রিপ্টরগুলো অভ্যন্তরীণভাবে BufferAllocator অবজেক্ট দ্বারা পরিচালিত হয়।
libion থেকে libdmabufheap এ পরিবর্তন করতে, ক্লায়েন্টদের আচরণ নিম্নরূপে পরিবর্তন করুন:
- অ্যালোকেশনের জন্য ব্যবহার করার হিপের নামটি মনে রাখুন, হেড আইডি/মাস্ক এবং হিপ ফ্ল্যাগের পরিবর্তে।
-
ion_alloc_fd()API-টি, যা একটি হিপ মাস্ক এবং ফ্ল্যাগ আর্গুমেন্ট গ্রহণ করে, তার পরিবর্তেBufferAllocator::Alloc()API-টি ব্যবহার করুন, যা এর বদলে একটি হিপ নেম গ্রহণ করে।
এই সারণিটি libion এবং libdmabufheap কীভাবে একটি আনক্যাশড সিস্টেম হিপ অ্যালোকেশন করে, তা দেখানোর মাধ্যমে এই পরিবর্তনগুলো তুলে ধরে।
| বরাদ্দের ধরণ | লিবিয়ন | 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 দ্বারা উন্মুক্ত প্রতিটি API- এর ডকুমেন্টেশন উপলব্ধ আছে। লাইব্রেরিটি C ক্লায়েন্টদের ব্যবহারের জন্য একটি হেডার ফাইলও উন্মুক্ত করে।
রেফারেন্স গ্র্যালক বাস্তবায়ন
Hikey960-এর gralloc ইমপ্লিমেন্টেশনটি libdmabufheap ব্যবহার করে, তাই আপনি এটিকে একটি রেফারেন্স ইমপ্লিমেন্টেশন হিসেবে ব্যবহার করতে পারেন।
প্রয়োজনীয় ueventd সংযোজন
যেকোনো নতুন ডিভাইস-নির্দিষ্ট DMA-BUF হিপ তৈরি করার জন্য, ডিভাইসটির ueventd.rc ফাইলে একটি নতুন এন্ট্রি যোগ করুন। DMA-BUF হিপ সমর্থন করার জন্য ueventd সেটআপ করার এই উদাহরণটি দেখায় যে DMA-BUF সিস্টেম হিপের জন্য এটি কীভাবে করা হয়।
প্রয়োজনীয় সেপলিসি সংযোজন
একটি ইউজারস্পেস ক্লায়েন্টকে নতুন DMA-BUF হিপ অ্যাক্সেস করার সুযোগ দিতে sepolicy পারমিশন যোগ করুন। এই প্রয়োজনীয় পারমিশন যোগ করার উদাহরণটি বিভিন্ন ক্লায়েন্টের DMA-BUF সিস্টেম হিপ অ্যাক্সেস করার জন্য তৈরি করা sepolicy পারমিশনগুলো দেখায়।
ফ্রেমওয়ার্ক কোড থেকে ভেন্ডর হিপস অ্যাক্সেস করুন
Treble-এর নিয়ম মেনে চলা নিশ্চিত করতে, ফ্রেমওয়ার্ক কোড শুধুমাত্র ভেন্ডর হিপের পূর্ব-অনুমোদিত বিভাগগুলো থেকেই মেমোরি বরাদ্দ করতে পারে।
অংশীদারদের কাছ থেকে প্রাপ্ত মতামতের ভিত্তিতে, গুগল দুই ধরনের ভেন্ডর হিপ শনাক্ত করেছে যেগুলোতে ফ্রেমওয়ার্ক কোড থেকে অবশ্যই অ্যাক্সেস করতে হবে:
- সিস্টেম হিপের উপর ভিত্তি করে গঠিত হিপ, যাতে ডিভাইস বা এসওসি-নির্দিষ্ট পারফরম্যান্স অপ্টিমাইজেশন অন্তর্ভুক্ত থাকে।
- সুরক্ষিত মেমরি থেকে প্রচুর জায়গা বরাদ্দ করতে হবে।
ডিভাইস বা এসওসি-নির্দিষ্ট পারফরম্যান্স অপ্টিমাইজেশন সহ সিস্টেম হিপের উপর ভিত্তি করে হিপস
এই ব্যবহারের ক্ষেত্রটিকে সমর্থন করার জন্য, ডিফল্ট DMA-BUF হিপ সিস্টেমের হিপ ইমপ্লিমেন্টেশনকে ওভাররাইড করা যেতে পারে।
-
gki_defconfigএCONFIG_DMABUF_HEAPS_SYSTEMবন্ধ করে দেওয়া হয়েছে, যাতে এটি একটি ভেন্ডর মডিউল হতে পারে। - VTS কমপ্লায়েন্স টেস্ট নিশ্চিত করে যে
/dev/dma_heap/systemএ হিপটি বিদ্যমান আছে। এই টেস্টগুলো আরও যাচাই করে যে, ইউজার স্পেস থেকে হিপটি অ্যালোকেট করা যায় এবং রিটার্ন করা ফাইল ডেসক্রিপ্টর (fd)-কে ইউজার স্পেস থেকে মেমোরি-ম্যাপ (mmapped) করা যায়।
পূর্ববর্তী বিষয়গুলো সিস্টেম হিপের আনক্যাশড সংস্করণের ক্ষেত্রেও প্রযোজ্য, যদিও সম্পূর্ণ IO-সমন্বিত ডিভাইসগুলোর জন্য এর অস্তিত্ব বাধ্যতামূলক নয়।
সুরক্ষিত মেমরি থেকে হিপস বরাদ্দ করতে হবে
যেহেতু অ্যান্ড্রয়েড কমন কার্নেল কোনো জেনেরিক সিকিউর হিপ ইমপ্লিমেন্টেশন সমর্থন করে না, তাই সিকিউর হিপ ইমপ্লিমেন্টেশন অবশ্যই ভেন্ডর-নির্দিষ্ট হতে হবে।
- আপনার ভেন্ডর-নির্দিষ্ট ইমপ্লিমেন্টেশনগুলিকে
/dev/dma_heap/system-secure<vendor-suffix>হিসেবে রেজিস্টার করুন। - এই হিপ ইমপ্লিমেন্টেশনগুলো ঐচ্ছিক।
- হিপ মেমরি বিদ্যমান থাকলে, VTS টেস্ট নিশ্চিত করে যে সেখান থেকে মেমরি বরাদ্দ করা যাবে।
- ফ্রেমওয়ার্ক কম্পোনেন্টগুলোকে এই হিপগুলোতে অ্যাক্সেস দেওয়া হয়, যাতে তারা Codec2 HAL/নন-বাইন্ডারাইজড, একই-প্রসেস HAL-এর মাধ্যমে হিপ ব্যবহার সক্ষম করতে পারে। তবে, জেনেরিক অ্যান্ড্রয়েড ফ্রেমওয়ার্ক ফিচারগুলো তাদের ইমপ্লিমেন্টেশন ডিটেইলসের ভিন্নতার কারণে এগুলোর উপর নির্ভরশীল হতে পারে না। ভবিষ্যতে যদি অ্যান্ড্রয়েড কমন কার্নেলে কোনো জেনেরিক সিকিওর হিপ ইমপ্লিমেন্টেশন যুক্ত করা হয়, তবে ডিভাইস আপগ্রেড করার সাথে দ্বন্দ্ব এড়াতে এটিকে অবশ্যই একটি ভিন্ন ABI ব্যবহার করতে হবে।
DMA-BUF হিপের জন্য কোডেক ২ অ্যালোকেটর
AOSP-তে DMA-BUF হিপস ইন্টারফেসের জন্য একটি codec2 অ্যালোকেটর উপলব্ধ আছে।
কম্পোনেন্ট স্টোর ইন্টারফেস, যার মাধ্যমে C2 HAL থেকে হিপ প্যারামিটার নির্দিষ্ট করা যায়, তা C2 DMA-BUF হিপ অ্যালোকেটরের সাথে উপলব্ধ।
একটি আয়ন হিপের নমুনা রূপান্তর প্রবাহ
ION থেকে DMA-BUF হিপে রূপান্তর মসৃণ করার জন্য, libdmabufheap একবারে একটি করে হিপ পরিবর্তন করার সুযোগ দেয়। নিম্নলিখিত ধাপগুলো my_heap নামের একটি নন-লেগ্যাসি ION হিপ পরিবর্তনের জন্য একটি প্রস্তাবিত কর্মপ্রবাহ প্রদর্শন করে, যা ION_FLAG_MY_FLAG নামক একটি ফ্ল্যাগ সমর্থন করে।
ধাপ ১: DMA-BUF ফ্রেমওয়ার্কে ION হিপের সমতুল্য কাঠামো তৈরি করুন। এই উদাহরণে, যেহেতু my_heap ION হিপটি ION_FLAG_MY_FLAG ফ্ল্যাগটি সমর্থন করে, তাই আমরা দুটি DMA-BUF হিপ রেজিস্টার করব:
-
my_heapআচরণটি,ION_FLAG_MY_FLAGফ্ল্যাগটি নিষ্ক্রিয় থাকা অবস্থায় `ION heap`-এর আচরণের সাথে হুবহু মিলে যায়। -
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 অবজেক্ট ইনস্ট্যানশিয়েট করুন এবং <ION heap name/mask, flag> কম্বিনেশনকে সমতুল্য DMA-BUF হিপের নামে ম্যাপ করার জন্য MapNameToIonHeap() API ব্যবহার করুন।
উদাহরণস্বরূপ:
allocator->MapNameToIonHeap("my_heap_special" /* name of DMA-BUF heap */, "my_heap" /* name of the ION heap */, ION_FLAG_MY_FLAG /* ion flags */ )
name এবং flag প্যারামিটার সহ MapNameToIonHeap() API ব্যবহার করার পরিবর্তে, আপনি ION heap name প্যারামিটারটিকে খালি রেখে <ION heap mask, flag> থেকে সমতুল্য DMA-BUF heap name-এ ম্যাপিং তৈরি করতে পারেন।
ধাপ ৪: উপযুক্ত হিপ নামটি ব্যবহার করে ion_alloc_fd() কলগুলোকে BufferAllocator::Alloc() দ্বারা প্রতিস্থাপন করুন।
| বরাদ্দের ধরণ | লিবিয়ন | libdmabufheap |
|---|---|---|
ION_FLAG_MY_FLAG ফ্ল্যাগটি সেট না করা অবস্থায় my_heap থেকে অ্যালোকেশন। | ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP, 0, &fd) | allocator->Alloc("my_heap", size) |
ION_FLAG_MY_FLAG ফ্ল্যাগ সেট করে my_heap থেকে অ্যালোকেশন। | 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 পারমিশন তৈরি করুন। ক্লায়েন্ট এখন নতুন DMA-BUF হিপ থেকে মেমরি বরাদ্দ করার জন্য সম্পূর্ণরূপে প্রস্তুত।
ধাপ ৬: logcat পরীক্ষা করে যাচাই করুন যে অ্যালোকেশনগুলো নতুন DMA-BUF হিপ থেকে হচ্ছে কিনা।
ধাপ ৭: কার্নেলে my_heap ION হিপটি নিষ্ক্রিয় করুন। যদি ক্লায়েন্ট কোডের ডিভাইস আপগ্রেড করার প্রয়োজন না হয় (যেগুলোর কার্নেল শুধুমাত্র ION হিপ সমর্থন করতে পারে), তাহলে আপনি MapNameToIonHeap() কলগুলোও সরিয়ে ফেলতে পারেন।