الانتقال من ION إلى أكوام DMA-BUF

في Android 12، يستبدل GKI 2.0 مُخصص ION بأكوام DMA-BUF للأسباب التالية:

  • الأمان: نظرًا لأن كل كومة DMA-BUF عبارة عن جهاز أحرف منفصل، فيمكن التحكم في الوصول إلى كل كومة بشكل منفصل باستخدام سياسة الخصوصية. لم يكن هذا ممكنًا مع ION لأن التخصيص من أي كومة يتطلب فقط الوصول إلى جهاز /dev/ion .
  • استقرار ABI: على عكس ION، فإن واجهة IOCTL الخاصة بإطار عمل DMA-BUF هي مضمونة لتكون مستقرة ABI لأنه يتم صيانتها في Linux kernel الأساسي.
  • التقييس: يوفر إطار عمل أكوام DMA-BUF واجهة UAPI محددة جيدًا. سمح ION بالإعلام المخصص ومعرفات الكومة التي حالت دون تطوير إطار عمل اختبار مشترك لأن تنفيذ ION لكل جهاز يمكن أن يتصرف بشكل مختلف.

قام فرع android12-5.10 من Android Common Kernel بتعطيل CONFIG_ION في 1 مارس 2021 .

خلفية

فيما يلي مقارنة مختصرة بين أكوام ION وDMA-BUF.

أوجه التشابه بين إطار عمل أكوام ION وDMA-BUF

  • تعد أطر عمل أكوام ION وDMA-BUF من مصدري DMA-BUF المستندين إلى الكومة.
  • كلاهما يسمحان لكل كومة بتحديد المخصص الخاص بها وعمليات DMA-BUF.
  • أداء التخصيص مشابه لأن كلا النظامين يحتاجان إلى IOCTL واحد للتخصيص.

الاختلافات بين إطار عمل أكوام ION وDMA-BUF

أكوام ايون أكوام 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.

نقل برامج تشغيل kernel من ION إلى أكوام DMA-BUF

تقوم برامج تشغيل Kernel بتنفيذ أكوام ION

تسمح كل من أكوام ION وDMA-BUF لكل كومة بتنفيذ مخصصاتها وعمليات DMA-BUF الخاصة بها. لذلك يمكنك التبديل من تطبيق كومة الذاكرة المؤقتة ION إلى تطبيق كومة الذاكرة المؤقتة DMA-BUF باستخدام مجموعة مختلفة من واجهات برمجة التطبيقات (API) لتسجيل الكومة. يعرض هذا الجدول واجهات برمجة تطبيقات تسجيل كومة ION وواجهات برمجة تطبيقات كومة DMA-BUF المكافئة لها.

أكوام ايون أكوام 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() . لتسهيل مشاركة التعليمات البرمجية، يوصى بتسجيل كافة المتغيرات لنفس الكومة داخل نفس برنامج التشغيل. يُظهر مثال dma-buf: system_heap هذا تنفيذ المتغيرات المخزنة مؤقتًا وغير المخزنة مؤقتًا لكومة النظام.

استخدم قالب dma-buf: heaps: المثال لإنشاء كومة DMA-BUF من البداية.

تقوم برامج تشغيل Kernel بالتخصيص مباشرة من أكوام ION

يوفر إطار عمل أكوام DMA-BUF أيضًا واجهة تخصيص لعملاء kernel. بدلاً من تحديد قناع الكومة والإشارات لتحديد نوع التخصيص، تأخذ الواجهة التي توفرها أكوام DMA-BUF اسم الكومة كمدخل.

يوضح ما يلي واجهة برمجة تطبيقات تخصيص ION داخل kernel وواجهات برمجة تطبيقات تخصيص الكومة DMA-BUF المكافئة لها. يمكن لبرامج تشغيل Kernel استخدام dma_heap_find() API للاستعلام عن وجود الكومة. تقوم واجهة برمجة التطبيقات (API) بإرجاع مؤشر إلى مثيل البنية dma_heap ، والذي يمكن بعد ذلك تمريره كوسيطة إلى واجهة برمجة تطبيقات dma_heap_buffer_alloc() .

أكوام ايون أكوام 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)

برامج تشغيل Kernel التي تستخدم DMA-BUFs

لا توجد تغييرات مطلوبة لبرامج التشغيل التي تستورد DMA-BUFs فقط، لأن المخزن المؤقت المخصص من كومة ION يتصرف تمامًا مثل المخزن المؤقت المخصص من كومة DMA-BUF المكافئة.

نقل عملاء مساحة المستخدم من ION إلى أكوام DMA-BUF

لتسهيل عملية الانتقال لعملاء ION في مساحة المستخدم، تتوفر مكتبة تجريد تسمى libdmabufheap . يدعم libdmabufheap التخصيص في أكوام DMA-BUF وأكوام ION. فهو يتحقق أولاً من وجود كومة DMA-BUF بالاسم المحدد، وإذا لم يكن الأمر كذلك، فإنه يعود إلى كومة ION مكافئة، في حالة وجودها.

يجب على العملاء تهيئة كائن BufferAllocator أثناء التهيئة بدلاً من فتح /dev/ion using ion_open() . وذلك لأن واصفات الملفات التي تم إنشاؤها عن طريق فتح /dev/ion و /dev/dma_heap/<heap_name> تتم إدارتها داخليًا بواسطة كائن BufferAllocator .

للتبديل من libion ​​إلى libdmabufheap ، قم بتعديل سلوك العملاء كما يلي:

  • تتبع اسم الكومة لاستخدامه في التخصيص، بدلاً من معرف/قناع الرأس وعلامة الكومة.
  • استبدل واجهة برمجة التطبيقات ion_alloc_fd() ، التي تأخذ قناع الكومة ووسيطة العلامة، بواجهة برمجة التطبيقات 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)

ينتظر متغير كومة النظام غير المخزنة مؤقتًا الموافقة الأولية ولكنه بالفعل جزء من فرع android12-5.10 .

لدعم ترقية الأجهزة، تسمح واجهة برمجة التطبيقات MapNameToIonHeap() بتعيين اسم الكومة لمعلمات الكومة ION (اسم الكومة/القناع والأعلام) للسماح لهذه الواجهات أيضًا باستخدام عمليات التخصيص المستندة إلى الاسم. فيما يلي مثال للتخصيص المستند إلى الاسم .

الوثائق الخاصة بكل واجهة برمجة تطبيقات يتم كشفها بواسطة libdmabufheap متاحة. تعرض المكتبة أيضًا ملف رأس للاستخدام من قبل عملاء C.

مرجع تنفيذ Gralloc

يستخدم تطبيق Hikey960 gralloc libdmabufheap ، لذا يمكنك استخدامه كتطبيق مرجعي .

الإضافات ueventd المطلوبة

بالنسبة لأي أكوام DMA-BUF جديدة خاصة بالجهاز تم إنشاؤها، قم بإضافة إدخال جديد إلى ملف ueventd.rc الخاص بالجهاز. يوضح مثال الإعداد الذي تم تنفيذه لدعم أكوام DMA-BUF كيفية إجراء ذلك لكومة نظام DMA-BUF.

الإضافات sepolicy المطلوبة

قم بإضافة أذونات sepolicy لتمكين عميل مساحة المستخدم من الوصول إلى كومة DMA-BUF جديدة. يُظهر مثال إضافة الأذونات المطلوبة أذونات الخصوصية التي تم إنشاؤها لعملاء مختلفين للوصول إلى كومة نظام DMA-BUF.

الوصول إلى أكوام البائع من رمز الإطار

لضمان التوافق مع Treble، لا يمكن تخصيص كود إطار العمل إلا من الفئات المعتمدة مسبقًا لأكوام الموردين.

بناءً على التعليقات الواردة من الشركاء، حددت Google فئتين من أكوام الموردين التي يجب الوصول إليها من رمز إطار العمل:

  1. الأكوام التي تعتمد على كومة النظام مع تحسينات الأداء الخاصة بالجهاز أو شركة SoC.
  2. أكوام للتخصيص من الذاكرة المحمية.

تعتمد الأكوام على كومة النظام مع تحسينات الأداء الخاصة بالجهاز أو شركة SoC

لدعم حالة الاستخدام هذه، يمكن تجاوز تطبيق الكومة لنظام الكومة DMA-BUF الافتراضي.

  • تم إيقاف تشغيل CONFIG_DMABUF_HEAPS_SYSTEM في gki_defconfig للسماح له بأن يكون وحدة بائع.
  • تضمن اختبارات توافق VTS وجود الكومة في /dev/dma_heap/system . تتحقق الاختبارات أيضًا من أنه يمكن تخصيص الكومة من، وأن واصف الملف الذي تم إرجاعه ( fd ) يمكن تعيينه للذاكرة (mmapped) من مساحة المستخدم.

تنطبق النقاط السابقة أيضًا على النسخة غير المخزنة مؤقتًا من كومة النظام، على الرغم من أن وجودها ليس إلزاميًا بالنسبة للأجهزة المتماسكة بالكامل للإدخال والإدخال.

أكوام للتخصيص من الذاكرة المحمية

يجب أن تكون تطبيقات الكومة الآمنة خاصة بالمورد نظرًا لأن Android Common Kernel لا يدعم تطبيق الكومة الآمنة العامة.

  • سجل تطبيقاتك الخاصة بالمورد كـ /dev/dma_heap/system-secure<vendor-suffix> .
  • تطبيقات الكومة هذه اختيارية.
  • في حالة وجود الأكوام، تضمن اختبارات VTS إمكانية إجراء التخصيصات منها.
  • يتم تزويد مكونات إطار العمل بإمكانية الوصول إلى هذه الأكوام بحيث يمكنها تمكين استخدام الأكوام من خلال Codec2 HAL/HALs غير المرتبطة بنفس العملية. ومع ذلك، لا يمكن أن تعتمد ميزات إطار عمل Android العامة عليها بسبب التباين في تفاصيل تنفيذها. إذا تمت إضافة تنفيذ الكومة الآمنة العامة إلى Android Common Kernel في المستقبل، فيجب أن تستخدم واجهة برمجة التطبيقات (ABI) مختلفة لتجنب التعارضات مع أجهزة الترقية.

مُخصص برنامج الترميز 2 لأكوام DMA-BUF

يتوفر مُخصص برنامج الترميز 2 لواجهة أكوام DMA-BUF في AOSP.

تتوفر واجهة مخزن المكونات التي تسمح بتحديد معلمات الكومة من C2 HAL مع مخصص الكومة C2 DMA-BUF.

عينة من تدفق الانتقال لكومة ION

لتسهيل الانتقال من أكوام ION إلى DMA-BUF، يسمح libdmabufheap بالتبديل بين كومة كومة واحدة في كل مرة. توضح الخطوات التالية سير العمل المقترح لنقل كومة ION غير قديمة تسمى my_heap والتي تدعم علامة واحدة، ION_FLAG_MY_FLAG .

الخطوة 1: إنشاء مكافئات لكومة ION في إطار عمل DMA-BUF. في هذا المثال، نظرًا لأن كومة ION my_heap تدعم العلامة ION_FLAG_MY_FLAG ، فإننا نسجل مجموعتي DMA-BUF:

  • يتطابق سلوك my_heap تمامًا مع سلوك كومة ION مع تعطيل العلامة ION_FLAG_MY_FLAG .
  • يتطابق سلوك my_heap_special تمامًا مع سلوك كومة ION مع تمكين العلامة ION_FLAG_MY_FLAG .

الخطوة 2: قم بإنشاء تغييرات ueventd لمجموعتي my_heap و my_heap_special DMA-BUF الجديدتين. عند هذه النقطة، تكون الأكوام مرئية كـ /dev/dma_heap/my_heap و /dev/dma_heap/my_heap_special ، بالأذونات المقصودة.

الخطوة 3: بالنسبة للعملاء الذين يقومون بالتخصيص من my_heap ، قم بتعديل ملفات تعريفهم للربط بـ libdmabufheap . أثناء تهيئة العميل، قم بإنشاء كائن BufferAllocator واستخدم MapNameToIonHeap() API لتعيين مجموعة <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() API مع معلمات الاسم والعلامة، يمكنك إنشاء التعيين من <ION heap mask, flag> إلى أسماء كومة الذاكرة المؤقتة DMA-BUF المكافئة عن طريق تعيين معلمة اسم الكومة ION على فارغة.

الخطوة 4: استبدل استدعاءات 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.

الخطوة 5: قم بإنشاء أذونات الخصوصية المطلوبة للعميل للوصول إلى أكوام DMA-BUF الجديدة. أصبح العميل الآن مجهزًا بالكامل للتخصيص من كومة DMA-BUF الجديدة.

الخطوة 6: التحقق من حدوث عمليات التخصيص من كومة DMA-BUF الجديدة عن طريق فحص logcat .

الخطوة 7: قم بتعطيل كومة ION my_heap في النواة. إذا لم يكن رمز العميل بحاجة إلى دعم ترقية الأجهزة (التي قد تدعم نواتها أكوام ION فقط)، فيمكنك أيضًا إزالة استدعاءات MapNameToIonHeap() .