ION থেকে DMA-BUF heaps-এ ট্রানজিশন (শুধুমাত্র 5.4 কার্নেল)

Android 12-এ, GKI 2.0 নিম্নলিখিত কারণে ION অ্যালোকেটরকে DMA-BUF হিপ দিয়ে প্রতিস্থাপন করে:

  • নিরাপত্তা: প্রতিটি DMA-BUF হিপ একটি আলাদা ক্যারেক্টার ডিভাইস হওয়ার কারণে, sepolicy-এর মাধ্যমে প্রতিটি হিপের অ্যাক্সেস আলাদাভাবে নিয়ন্ত্রণ করা যায়। ION-এর ক্ষেত্রে এটি সম্ভব ছিল না কারণ কোনও হিপ থেকে অ্যালোকেশন করতে শুধুমাত্র /dev/ion ডিভাইসের অ্যাক্সেস প্রয়োজন।
  • ABI স্থিতিশীলতা: ION-এর মতো, DMA-BUF হিপ ফ্রেমওয়ার্কের IOCTL ইন্টারফেস হল ABI স্থিতিশীল কারণ এটি আপস্ট্রিম Linux কার্নেলে রক্ষণাবেক্ষণ করা হয়।
  • স্ট্যান্ডার্ডাইজেশন: DMA-BUF হিপস ফ্রেমওয়ার্ক একটি সুনির্দিষ্ট UAPI অফার করে। ION কাস্টম ফ্ল্যাগ ও হিপ আইডি অনুমোদিত হওয়ায়, সাধারণ টেস্টিং ফ্রেমওয়ার্ক ডেভেলপ করা যায়নি, কারণ প্রতিটি ডিভাইসের ION ইমপ্লিমেন্টেশন আলাদা আলাদা আচরণ করতে পারে।

১ মার্চ, ২০২১-এ Android Common Kernel-এর android12-5.10 ব্রাঞ্চ বন্ধ করা হয়েছে CONFIG_ION।

ব্যাকগ্রাউন্ড

ION এবং DMA-BUF হিপের মধ্যে সংক্ষিপ্ত তুলনা নিচে দেওয়া হল।

ION ও DMA-BUF হিপ ফ্রেমওয়ার্কের মধ্যে মিল

  • ION এবং DMA-BUF হিপ ফ্রেমওয়ার্ক, দুটিই হিপ-ভিত্তিক DMA-BUF এক্সপোর্টার।
  • এই দুটিই প্রতিটি হিপকে তার নিজস্ব অ্যালোকেটর এবং DMA-BUF অপস সংজ্ঞায়িত করতে দেয়।
  • অ্যালোকেশন পারফর্ম্যান্স একই রকম কারণ অ্যালোকেশনের জন্য দুটি স্কিমেরই একটি IOCTL প্রয়োজন।

ION এবং DMA-BUF হিপ ফ্রেমওয়ার্কের মধ্যে পার্থক্য

ION হিপ DMA-BUF হিপ
/dev/ion-এর মাধ্যমে সব 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 অপারেশন প্রয়োগ করার অনুমতি দেয়। তাই, আপনি হিপ রেজিস্টার করার জন্য API-এর একটি আলাদা সেট ব্যবহার করে ION হিপ ইমপ্লিমেন্টেশন থেকে DMA-BUF হিপ ইমপ্লিমেন্টেশনে পরিবর্তন করতে পারবেন। এই সারণীতে ION হিপ রেজিস্ট্রেশন API এবং তার সমতুল্য DMA-BUF হিপ API দেখানো হয়েছে।

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 template ব্যবহার করুন।

কার্নেল ড্রাইভার সরাসরি ION হিপ থেকে বরাদ্দ করছে

এছাড়াও, DMA-BUF হিপ ফ্রেমওয়ার্ক ইন-কার্নেল ক্লায়েন্টদের জন্য অ্যালোকেশন ইন্টারফেস প্রদান করে। অ্যালোকেশনের ধরন বেছে নেওয়ার জন্য হিপ মাস্ক ও ফ্ল্যাগ নির্দিষ্ট করার পরিবর্তে, DMA-BUF হিপের মাধ্যমে অফার করা ইন্টারফেস ইনপুট হিসেবে হিপের নাম গ্রহণ করে।

নিচে ইন-কার্নেল ION অ্যালোকেশন API এবং এর সমতুল্য DMA-BUF হিপ অ্যালোকেশন API দেখানো হয়েছে। কার্নেল ড্রাইভার dma_heap_find() API ব্যবহার করে হিপের অস্তিত্ব সম্পর্কে কোয়েরি করতে পারে। API, struct dma_heap-এর একটি ইনস্ট্যান্সের পয়েন্টার রিটার্ন করে, যা পরে dma_heap_buffer_alloc() API-তে আর্গুমেন্ট হিসেবে পাস করা যেতে পারে।

ION হিপ DMA-BUF হিপ
struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)

struct dma_heap *dma_heap_find(const char *name)

struct dma_buf *struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, unsigned int fd_flags, unsigned int heap_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 কীভাবে একটি আনক্যাশড সিস্টেম হিপ অ্যালোকেশন করে তা দেখিয়ে এই পরিবর্তনগুলি ব্যাখ্যা করে।

অ্যালোকেশনের ধরন 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)

The uncached system heap variant আপস্ট্রিম অনুমোদনের অপেক্ষায় আছে কিন্তু এটি ইতিমধ্যেই android12-5.10 ব্রাঞ্চের অংশ।

ডিভাইস আপগ্রেড করার সুবিধা দিতে, MapNameToIonHeap() API, ION হিপ প্যারামিটারের (হিপ নাম বা মাস্ক ও ফ্ল্যাগ) সাথে হিপ নাম ম্যাপ করার অনুমতি দেয়, যাতে সেইসব ইন্টারফেস নাম-ভিত্তিক অ্যালোকেশন ব্যবহার করতে পারে। এখানে নাম-ভিত্তিক অ্যালোকেশন উদাহরণ দেওয়া হল।

এর মাধ্যমে এক্সপোজ করা libdmabufheap প্রতিটি API-এর ডকুমেন্টেশন উপলভ্য। এছাড়াও, C ক্লায়েন্টদের ব্যবহারের জন্য লাইব্রেরি একটি হেডার ফাইল প্রকাশ করে।

রেফারেন্স Gralloc ইমপ্লিমেন্টেশন

Hikey960 gralloc ইমপ্লিমেন্টেশনে libdmabufheap ব্যবহার করা হয়, তাই আপনি এটিকে রেফারেন্স ইমপ্লিমেন্টেশন হিসেবে ব্যবহার করতে পারেন।

ueventd-তে প্রয়োজনীয় সংযোজন

তৈরি করা যেকোনও নতুন ডিভাইস-নির্দিষ্ট DMA-BUF হিপের জন্য, ডিভাইসের ueventd.rc ফাইলে একটি নতুন এন্ট্রি যোগ করুন। এই DMA-BUF হিপ কাজ করার জন্য ueventd সেট-আপ করুন উদাহরণ DMA-BUF সিস্টেম হিপের জন্য এটি কীভাবে করা হয় তা দেখায়।

প্রয়োজনীয় sepolicy সংযোজন

ব্যবহারকারীর স্পেস ক্লায়েন্টকে নতুন DMA-BUF হিপ অ্যাক্সেস করার অনুমতি দিতে sepolicy অনুমতি যোগ করুন। এই প্রয়োজনীয় অনুমতি যোগ করুন উদাহরণটি DMA-BUF সিস্টেম হিপ অ্যাক্সেস করার জন্য বিভিন্ন ক্লায়েন্টের জন্য তৈরি করা sepolicy অনুমতি দেখায়।

ফ্রেমওয়ার্ক কোড থেকে ভেন্ডর হিপ অ্যাক্সেস করা

Treble-এর সাথে সামঞ্জস্য নিশ্চিত করতে, ফ্রেমওয়ার্ক কোড শুধুমাত্র ভেন্ডর হিপের আগে থেকে অনুমোদিত বিভাগ থেকে বরাদ্দ করতে পারে।

পার্টনারদের থেকে পাওয়া মতামতের ভিত্তিতে, Google দুই ধরনের ভেন্ডর হিপ শনাক্ত করেছে যা ফ্রেমওয়ার্ক কোড থেকে অ্যাক্সেস করতে হবে:

  1. ডিভাইস বা SoC-নির্দিষ্ট পারফর্ম্যান্স অপ্টিমাইজেশন সহ সিস্টেম হিপের উপর ভিত্তি করে তৈরি হিপ।
  2. সুরক্ষিত মেমরি থেকে অ্যালোকেট করার জন্য হিপ।

ডিভাইস বা SoC-নির্দিষ্ট পারফর্ম্যান্স অপ্টিমাইজেশন সহ সিস্টেম হিপের উপর ভিত্তি করে হিপ

এই ব্যবহারের ক্ষেত্রে সহায়তা করতে, ডিফল্ট DMA-BUF হিপ সিস্টেমের হিপ প্রয়োগ করার পদ্ধতি ওভাররাইড করা যেতে পারে।

  • CONFIG_DMABUF_HEAPS_SYSTEM-এ gki_defconfig বন্ধ করা আছে যাতে এটি ভেন্ডর মডিউল হতে পারে।
  • VTS কমপ্লায়েন্স টেস্ট নিশ্চিত করে যে /dev/dma_heap/system-এ হিপ আছে। এছাড়াও, টেস্টের মাধ্যমে যাচাই করা হয় যে হিপ বরাদ্দ করা যাবে কিনা এবং ফেরত পাঠানো ফাইল ডেসক্রিপটর (fd) ব্যবহারকারীর স্পেস থেকে মেমরি-ম্যাপ (mmapped) করা যাবে কিনা।

সিস্টেম হিপের আনক্যাশড ভ্যারিয়েন্টের ক্ষেত্রেও উপরের পয়েন্টগুলি প্রযোজ্য, যদিও সম্পূর্ণ IO-কোহেরেন্ট ডিভাইসের ক্ষেত্রে এটির অস্তিত্ব বাধ্যতামূলক নয়।

সুরক্ষিত মেমরি থেকে অ্যালোকেট করার জন্য হিপ

নিরাপদ হিপ ইমপ্লিমেন্টেশন অবশ্যই ভেন্ডর-নির্দিষ্ট হতে হবে কারণ Android কমন কার্নেল একটি জেনেরিক নিরাপদ হিপ ইমপ্লিমেন্টেশন সমর্থন করে না।

  • আপনার ভেন্ডর-নির্দিষ্ট প্রয়োগ /dev/dma_heap/system-secure<vendor-suffix> হিসেবে রেজিস্টার করুন।
  • এইসব হিপ প্রয়োগ করা ঐচ্ছিক।
  • হিপ থাকলে, VTS পরীক্ষা নিশ্চিত করে যে সেগুলি থেকে অ্যালোকেশন করা যাবে।
  • ফ্রেমওয়ার্ক কম্পোনেন্টকে এই হিপে অ্যাক্সেস দেওয়া হয় যাতে তারা Codec2 HAL/non-binderized, একই প্রসেস HAL-এর মাধ্যমে হিপ ব্যবহার চালু করতে পারে। তবে, সাধারণ Android ফ্রেমওয়ার্ক ফিচারগুলি সেগুলির উপর নির্ভর করতে পারে না, কারণ সেগুলির প্রয়োগের বিবরণে পরিবর্তনশীলতা থাকে। ভবিষ্যতে Android কমন কার্নেলে একটি জেনেরিক সুরক্ষিত হিপ ইমপ্লিমেন্টেশন যোগ করা হলে, আপগ্রেড করা ডিভাইসের সাথে বিরোধ এড়াতে এটিকে অবশ্যই একটি ভিন্ন ABI ব্যবহার করতে হবে।

DMA-BUF হিপের জন্য কোডেক ২ অ্যালোকেটর

AOSP-তে DMA-BUF heaps ইন্টারফেসের জন্য codec2 অ্যালোকেটর উপলভ্য।

C2 DMA-BUF হিপ অ্যালোকেটরের সাথে কম্পোনেন্ট স্টোর ইন্টারফেস উপলভ্য থাকে যা C2 HAL থেকে হিপ প্যারামিটার নির্দিষ্ট করার অনুমতি দেয়।

ION হিপের জন্য স্যাম্পেল ট্রানজিশন ফ্লো

ION থেকে DMA-BUF হিপে ট্রানজিশন মসৃণ করতে, libdmabufheap একবারে একটি হিপ পরিবর্তন করার অনুমতি দেয়। নিচে দেখানো ধাপগুলি my_heap নামের একটি নন-লেগ্যাসি ION হিপকে ট্রানজিট করার জন্য সাজেস্ট করা ওয়ার্কফ্লো দেখায়, যা একটি ফ্ল্যাগ, ION_FLAG_MY_FLAG-কে সাপোর্ট করে।

ধাপ ১: DMA-BUF ফ্রেমওয়ার্কে ION হিপের সমতুল্য কিছু তৈরি করুন। এই উদাহরণে, ION হিপ my_heap একটি ফ্ল্যাগ ION_FLAG_MY_FLAG সমর্থন করে বলে, আমরা দুটি DMA-BUF হিপ রেজিস্টার করি:

  • my_heap-এর আচরণ ION হিপের আচরণের সাথে হুবহু মেলে, যেখানে ফ্ল্যাগ ION_FLAG_MY_FLAG বন্ধ করা আছে।
  • my_heap_special-এর আচরণ ঠিক সেইসব ION হিপের আচরণের সাথে মেলে যেখানে ION_FLAG_MY_FLAG ফ্ল্যাগ চালু করা আছে।

ধাপ ২: নতুন my_heap এবং my_heap_special DMA-BUF হিপের জন্য ueventd পরিবর্তন তৈরি করুন। এই পর্যায়ে, হিপগুলি /dev/dma_heap/my_heap ও /dev/dma_heap/my_heap_special হিসেবে দেখা যায়, সাথে প্রত্যাশিত অনুমতিও থাকে।

ধাপ ৩: my_heap থেকে বরাদ্দ করা ক্লায়েন্টের জন্য, libdmabufheap-এর সাথে লিঙ্ক করতে তাদের মেকফাইল পরিবর্তন করুন। ক্লায়েন্ট ইনিশিয়ালাইজেশনের সময়, একটি BufferAllocator অবজেক্ট ইনস্ট্যানশিয়েট করুন এবং সমতুল্য DMA-BUF হিপ নামের সাথে <ION heap name/mask, flag> কম্বিনেশন ম্যাপ করতে 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 */ )

নাম ও ফ্ল্যাগ প্যারামিটার সহ MapNameToIonHeap() API ব্যবহার করার পরিবর্তে, আপনি ION হিপ নামের প্যারামিটার খালি রেখে <ION heap mask, flag> থেকে সমতুল্য DMA-BUF হিপ নামে ম্যাপিং তৈরি করতে পারেন।

ধাপ ৪: উপযুক্ত হিপ নাম ব্যবহার করে 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 অনুমতি তৈরি করুন। ক্লায়েন্ট এখন নতুন DMA-BUF হিপ থেকে মেমরি বরাদ্দ করার জন্য সম্পূর্ণভাবে প্রস্তুত।

ধাপ ৬: নতুন DMA-BUF হিপ থেকে অ্যাসাইনমেন্ট হচ্ছে কিনা তা logcat পরীক্ষা করে দেখুন।

ধাপ ৭: কার্নেলে ION হিপ my_heap বন্ধ করুন। ক্লায়েন্ট কোডে আপগ্রেড করা ডিভাইস (যার কার্নেল শুধু ION হিপ সাপোর্ট করতে পারে) সাপোর্ট করার প্রয়োজন না হলে, আপনি MapNameToIonHeap() ইনভোকেশনও সরিয়ে দিতে পারেন।