RenderScript

RenderScript چارچوبی برای اجرای وظایف محاسباتی سنگین با عملکرد بالا در Android است. این زبان برای استفاده با محاسبات داده-موازی طراحی شده است، هرچند که حجم‌های کاری ترتیبی نیز می‌توانند از آن بهره‌مند شوند. زمان اجرای RenderScript کار را در پردازنده‌های موجود در دستگاه، مانند CPUهای چندهسته‌ای و GPUها، موازی می‌کند و به توسعه‌دهندگان امکان می‌دهد به‌جای زمان‌بندی کار، بر بیان الگوریتم‌ها تمرکز کنند. ‫RenderScript به‌ویژه برای برنامه‌هایی که پردازش تصویر، عکاسی محاسباتی، یا دید رایانه‌ای انجام می‌دهند مفید است.

دستگاه‌های دارای Android 8.0 و بالاتر از چارچوب RenderScript و HALهای فروشنده زیر استفاده می‌کنند:

شکل ۱. کد فروشنده به کتابخانه‌های داخلی پیوند می‌دهد.

تفاوت‌های RenderScript در Android 7.x و نسخه‌های پایین‌تر شامل موارد زیر است:

  • دو نمونه از کتابخانه‌های داخلی RenderScript در یک فرایند. یک مجموعه برای مسیر بازگشت CPU است و مستقیماً از /system/lib است؛ مجموعه دیگر برای مسیر GPU است و از /system/lib/vndk-sp است.
  • کتابخانه‌های داخلی RS در /system/lib به‌عنوان بخشی از پلاتفرم ساخته می‌شوند و با ارتقا یافتن system.img به‌روزرسانی می‌شوند. بااین‌حال، libs در /system/lib/vndk-sp برای فروشنده ساخته شده است و وقتی system.img ارتقا می‌یابد به‌روز نمی‌شود (اگرچه می‌توان آن‌ها را برای رفع نقص امنیتی به‌روز کرد، اما ABI آن‌ها یکسان باقی می‌ماند).
  • کد فروشنده (RS HAL،‏ RS driver، و bcc plugin) با کتابخانه‌های داخلی RenderScript واقع در /system/lib/vndk-sp پیوند داده شده است. آن‌ها نمی‌توانند به کتابخانه‌های موجود در /system/lib پیوند دهند زیرا کتابخانه‌های موجود در آن دایرکتوری برای پلاتفرم ساخته شده‌اند و بنابراین ممکن است با کد فروشنده سازگار نباشند (یعنی ممکن است نمادها برداشته شوند). انجام این کار باعث می‌شود OTA فقط چارچوب غیرممکن شود.

طراحی

بخش‌های زیر جزئیات طراحی RenderScript را در Android 8.0 و بالاتر شرح می‌دهند.

کتابخانه‌های RenderScript دردسترس فروشندگان

این بخش کتابخانه‌های RenderScript (معروف به Vendor NDK برای Same-Process HALs یا VNDK-SP) را که برای کد فروشنده دردسترس است و می‌توان به آن پیوند داد فهرست می‌کند. همچنین کتابخانه‌های اضافی را که با RenderScript مرتبط نیستند اما به کد فروشنده ارائه می‌شوند، شرح می‌دهد.

اگرچه فهرست زیر از کتابخانه‌ها ممکن است بین نسخه‌های Android متفاوت باشد، اما برای یک نسخه خاص Android تغییرناپذیر است؛ برای فهرست به‌روز کتابخانه‌های دردسترس، به /system/etc/ld.config.txt مراجعه کنید.

RenderScript Libs کتابخانه‌های غیر RenderScript
  • android.hardware.graphics.renderscript@1.0.so
  • libRS_internal.so
  • libRSCpuRef.so
  • libblas.so
  • libbcinfo.so
  • libcompiler_rt.so
  • libRSDriver.so
  • libc.so
  • libm.so
  • libdl.so
  • libstdc++.so
  • liblog.so
  • libnativewindow.so
  • libsync.so
  • libvndksupport.so
  • libbase.so
  • libc++.so
  • libcutils.so
  • libutils.so
  • libhardware.so
  • libhidlbase.so
  • libhidltransport.so
  • libhwbinder.so
  • liblzma.so
  • libz.so
  • libEGL.so
  • libGLESv1_CM.so
  • libGLESv2.so

پیکربندی فضای نام پیونددهنده

محدودیت پیونددهی که مانع از استفاده کتابخانه‌هایی می‌شود که در VNDK-SP نیستند کد فروشنده در زمان اجرا بااستفاده از فضای نام پیونددهنده اعمال می‌شود. (برای جزئیات، به ارائه طراحی VNDK مراجعه کنید.)

در دستگاه‌های دارای Android 8.0 و بالاتر، همه «لایه‌های انتزاع سخت‌افزار هم‌فرایندی» (SP-HALs) به‌جز RenderScript در فضای نام پیونددهنده sphal بار می‌شوند. RenderScript در فضای نام مختص RenderScript rs بار می‌شود، مکانی که اجرای کمی آزادتر را برای کتابخانه‌های RenderScript ممکن می‌کند. چون پیاده‌سازی RS باید بیت‌کد کامپایل‌شده را بار کند، /data/*/*.so به مسیر فضای نام rs اضافه می‌شود (سایر SP-HALها مجاز نیستند کتابخانه‌ها را از پارتیشن داده بار کنند).

علاوه‌براین، فضای نام rs امکان استفاده از کتابخانه‌های بیشتری را نسبت به آنچه فضاهای نام دیگر ارائه می‌دهند فراهم می‌کند. ‫libmediandk.so و libft2.so به فضای نام rs عرضه می‌شوند زیرا libRS_internal.so به این کتابخانه‌ها وابستگی داخلی دارد.

شکل ۲. پیکربندی فضای نام برای پیونددهنده.

بار کردن درایورها

مسیر بازگشت به واحد پردازش مرکزی

بسته به وجود RS_CONTEXT_LOW_LATENCY بیت هنگام ایجاد بافت RS، مسیر CPU یا GPU انتخاب می‌شود. وقتی مسیر واحد پردازش مرکزی انتخاب می‌شود، libRS_internal.so (پیاده‌سازی اصلی چارچوب RS) مستقیماً از فضای نام پیونددهنده پیش‌فرض که در آن نسخه پلاتفرم کتابخانه‌های RS ارائه می‌شود dlopen می‌شود.

وقتی مسیر بازگشت CPU انتخاب می‌شود، از پیاده‌سازی RS HAL فروشنده اصلاً استفاده نمی‌شود و شیء RsContext با mVendorDriverName تهی ایجاد می‌شود. ‫libRSDriver.so (به‌طور پیش‌فرض) dlopen شده است و کتابخانه درایور از جای‌نام default بار می‌شود زیرا فراخواننده (libRS_internal.so) نیز در جای‌نام default بار شده است.

شکل ۳. مسیر جایگزین واحد پردازش مرکزی.

مسیر GPU

برای مسیر GPU،‏ libRS_internal.so به‌صورت متفاوتی بار می‌شود. ابتدا، libRS.so از android.hardware.renderscript@1.0.so (و libhidltransport.so زیرین آن) برای بار کردن android.hardware.renderscript@1.0-impl.so (پیاده‌سازی فروشنده RS HAL) در جای‌نام پیونددهنده دیگری به نام sphal استفاده می‌کند. سپس RS HAL dlopen libRS_internal.so را در فضای نام پیونددهنده دیگری به نام rs قرار می‌دهد.

فروشندگان می‌توانند با تنظیم پرچم زمان ساخت OVERRIDE_RS_DRIVER، که در پیاده‌سازی RS HAL (hardware/interfaces/renderscript/1.0/default/Context.cpp) جاسازی شده است، گرداننده RS خود را ارائه دهند. سپس این نام گرداننده برای بافت RS برای مسیر GPU dlopen می‌شود.

ایجاد شیء RsContext به پیاده‌سازی RS HAL واگذار شده است. HAL بااستفاده از تابع rsContextCreateVendor() با نام درایور برای استفاده به‌عنوان آرگومان، به چارچوب RS بازمی‌گردد. سپس چارچوب RS درایور مشخص‌شده را هنگام راه‌اندازی RsContext بار می‌کند. در این مورد، کتابخانه درایور در فضای نام rs بار می‌شود زیرا شیء RsContext در فضای نام rs ایجاد شده است و /vendor/lib در مسیر جستجوی فضای نام قرار دارد.

شکل ۴. مسیر عقب‌گرد GPU.

هنگام انتقال از فضای نام default به فضای نام sphal، libhidltransport.so از تابع android_load_sphal_library() برای مرتب کردن صریح پیونددهنده پویا برای بار کردن کتابخانه -impl.so از فضای نام sphal استفاده می‌کند.

هنگام انتقال از فضای نام sphal به فضای نام rs، بار کردن به‌طور غیرمستقیم با خط زیر در /system/etc/ld.config.txt انجام می‌شود:

namespace.sphal.link.rs.shared_libs = libRS_internal.so

این خط مشخص می‌کند که پیونددهنده پویا باید libRS_internal.so را از فضای نام rs بار کند، وقتی که کتابخانه نمی‌تواند از فضای نام sphal پیدا/بار شود (که همیشه این‌طور است چون فضای نام sphal در /system/lib/vndk-sp که libRS_internal.so در آن قرار دارد جستجو نمی‌کند). با این پیکربندی، یک فراخوانی ساده dlopen() به libRS_internal.so برای انتقال فضای نام کافی است.

بار کردن افزایه رونوشت مخفی

bcc plugin کتابخانه‌ای است که فروشنده ارائه کرده است و در کامپایلر bcc بار شده است. چون bcc فرایند سیستمی در دایرکتوری /system/bin است، کتابخانه bcc plugin را می‌توان «لایه انتزاع سخت‌افزار SP» (یعنی لایه انتزاع سخت‌افزار فروشنده که می‌تواند مستقیماً در فرایند سیستم بار شود بدون اینکه binderized شود) درنظر گرفت. به‌عنوان SP-HAL، کتابخانه bcc-plugin:

  • نمی‌توان به کتابخانه‌های فقط چارچوب مثل libLLVM.so پیوند داد.
  • فقط می‌تواند به کتابخانه‌های VNDK-SP که برای فروشنده دردسترس است پیوند دهد.

این محدودیت با بار کردن bcc plugin در فضای نام sphal بااستفاده از تابع android_sphal_load_library() اعمال می‌شود. در نسخه‌های قبلی Android، نام افزایه بااستفاده از گزینه -load مشخص می‌شد و کتابخانه بااستفاده از dlopen() ساده توسط libLLVM.so بار می‌شد. در Android نسخه ۸.۰ و بالاتر، این مورد در گزینه -plugin مشخص شده است و کتابخانه مستقیماً توسط خود bcc بار می‌شود. این گزینه مسیر غیرخاص Android را به پروژه متن‌باز LLVM فعال می‌کند.

شکل ۵. درحال بار کردن افزایه bcc،‏ Android نسخه ۷.x و پایین‌تر.



شکل ۶. درحال بار کردن افزایه bcc،‏ Android نسخه ۸.۰ و بالاتر.

مسیرهای جستجو برای ld.mc

هنگام اجرای ld.mc، برخی‌از کتابخانه‌های زمان اجرای RS به‌عنوان ورودی به پیونددهنده داده می‌شوند. کدبیت RS از برنامه دربرابر کتابخانه‌های زمان اجرا پیوند داده می‌شود و وقتی کدبیت تبدیل‌شده در فرایند برنامه بار می‌شود، کتابخانه‌های زمان اجرا دوباره به‌صورت پویا از کدبیت تبدیل‌شده پیوند داده می‌شوند.

کتابخانه‌های زمان اجرا شامل این موارد است:

  • libcompiler_rt.so
  • libm.so
  • libc.so
  • درایور RS (libRSDriver.so یا OVERRIDE_RS_DRIVER)

هنگام بار کردن کدبیت کامپایل‌شده در فرایند برنامه، دقیقاً همان کتابخانه‌ای را که ld.mc استفاده کرده است ارائه دهید. درغیراین‌صورت، کدبیت کامپایل‌شده ممکن است نمادی را که هنگام پیوند دردسترس بوده است پیدا نکند.

برای انجام این کار، چارچوب RS هنگام اجرای ld.mc از مسیرهای جستجوی مختلفی برای کتابخانه‌های زمان اجرا استفاده می‌کند، بسته به اینکه خود چارچوب RS از /system/lib یا از /system/lib/vndk-sp بارگیری شده باشد. این کار را می‌توان با خواندن نشانی نماد دلخواه کتابخانه چارچوب RS و استفاده از dladdr() برای دریافت مسیر فایل نگاشت‌شده به نشانی تعیین کرد.

خط‌مشی SELinux

در نتیجه تغییرات خط‌مشی SELinux در Android 8.0 و بالاتر، باید هنگام برچسب‌گذاری فایل‌های اضافی در پارتیشن vendor، از قوانین خاصی (اجراشده ازطریق neverallows) پیروی کنید:

  • vendor_file باید برچسب پیش‌فرض برای همه فایل‌ها در پارتیشن vendor باشد. خط‌مشی پلاتفرم برای دسترسی به پیاده‌سازی‌های HAL عبوردهنده به این مورد نیاز دارد.
  • همه exec_types جدید اضافه‌شده در پارتیشن vendor ازطریق SEPolicy فروشنده باید دارای مشخصه vendor_file_type باشد. این امر ازطریق neverallows اجرا می‌شود.
  • برای جلوگیری از تداخل با به‌روزرسانی‌های آینده پلاتفرم/چارچوب، از برچسب‌گذاری فایل‌های غیرexec_types در پارتیشن vendor خودداری کنید.
  • همه وابستگی‌های کتابخانه برای HALهای فرایند یکسان شناسایی‌شده توسط AOSP باید با same_process_hal_file برچسب‌گذاری شوند.

برای جزئیات مربوط به خط‌مشی SELinux، به Security-Enhanced Linux در Android مراجعه کنید.

سازگاری ABI برای بیت‌کد

اگر میانای برنامه‌سازی کاربردی جدیدی اضافه نشود، یعنی نسخه HAL ارتقا پیدا نکند، چارچوب‌های RS به استفاده از درایور GPU (HAL 1.0) موجود ادامه خواهند داد.

برای تغییرات جزئی HAL (HAL 1.1) که بر بیت‌کد تأثیر نمی‌گذارند، چارچوب‌ها باید برای این میاناهای برنامه‌سازی کاربردی جدیداً اضافه‌شده به CPU بازگردند و به استفاده از درایور GPU (HAL 1.0) در جاهای دیگر ادامه دهند.

برای تغییرات عمده HAL (‏HAL 2.0) که بر ترجمه/پیوند کدبیت تأثیر می‌گذارند، چارچوب‌های RS باید انتخاب کنند که درایورهای GPU ارائه‌شده توسط فروشنده را بارگیری نکنند و درعوض از مسیر CPU یا Vulkan برای شتاب‌دهی استفاده کنند.

مصرف کدبیت RenderScript در سه مرحله انجام می‌شود:

صحنه جزئیات
کامپایل کردن
  • بیت‌کد ورودی (.bc) برای bcc باید در قالب بیت‌کد LLVM 3.2 باشد و bcc باید با برنامه‌های موجود (قدیمی) سازگار باشد.
  • بااین‌حال، فراداده در .bc می‌تواند تغییر کند (ممکن است توابع زمان اجرای جدیدی وجود داشته باشد، برای مثال، تنظیم‌کننده‌ها و دریافت‌کننده‌های تخصیص، توابع ریاضی، و غیره). بخشی از عملکردهای زمان اجرا در libclcore.bc قرار دارد، بخشی از آن‌ها در LibRSDriver یا معادل فروشنده قرار دارد.
  • عملکردهای زمان اجرای جدید یا تغییرات فراداده‌ای که باعث خرابی می‌شوند نیازمند افزایش سطح میانای برنامه‌سازی کاربردی بیت‌کد هستند. چون درایورهای فروشنده نمی‌توانند آن را مصرف کنند، نسخه HAL نیز باید افزایش یابد.
  • فروشندگان ممکن است کامپایلرهای خودشان را داشته باشند، اما نتایج/الزامات bcc برای آن کامپایلرها نیز اعمال می‌شود.
پیوند
  • ‫.o کامپایل‌شده با درایور فروشنده پیوند داده خواهد شد، برای نمونه، libRSDriver_foo.so، و libcompiler_rt.so. مسیر CPU با libRSDriver.so پیوند خواهد شد.
  • اگر .o به میانای برنامه‌سازی کاربردی زمان اجرای جدیدی از libRSDriver_foo نیاز داشته باشد، درایور فروشنده باید به‌روز شود تا از آن پشتیبانی کند.
  • برخی‌از فروشندگان ممکن است پیونددهنده‌های خود را داشته باشند، اما استدلال برای ld.mc برای آن‌ها نیز اعمال می‌شود.
بار کردن
  • ‫libRSCpuRef شیء هم‌رسانی‌شده را بار می‌کند. اگر تغییراتی در این میان‌گیری وجود داشته باشد، به تغییر نسخه HAL نیاز است.
  • فروشندگان یا برای بار کردن شیء مشترک به libRSCpuRef تکیه می‌کنند یا شیء خودشان را پیاده‌سازی می‌کنند.

علاوه‌بر HAL، میاناهای برنامه‌سازی کاربردی زمان اجرا و نشان‌های صادرشده نیز واسط هستند. هیچ‌یک از این میان‌ها از زمان Android 7.0 (API 24) تغییر نکرده است و هیچ برنامه فوری‌ای برای تغییر آن در Android 8.0 و نسخه‌های بالاتر وجود ندارد. بااین‌حال، اگر میانای تغییر کند، نسخه HAL نیز افزایش می‌یابد.

پیاده‌سازی‌های ارائه‌دهنده

‫Android نسخه ۸.۰ و بالاتر برای اینکه درایور «واحد پردازش گرافیکی» به‌درستی کار کند، به تغییراتی در درایور «واحد پردازش گرافیکی» نیاز دارد.

پیمانه‌های درایور

  • واحدهای راه‌انداز نباید به هیچ‌یک از کتابخانه‌های سیستمی که در فهرست نیستند وابسته باشند.
  • Driver باید android.hardware.renderscript@1.0-impl_{NAME} خودش را ارائه دهد، یا پیاده‌سازی پیش‌فرض android.hardware.renderscript@1.0-impl را به‌عنوان وابستگی‌اش اعلام کند.
  • پیاده‌سازی CPU‏ libRSDriver.so نمونه خوبی از نحوه برداشتن وابستگی‌های غیر VNDK-SP است.

گردآورنده بیت‌کد

می‌توانید کد شیء RenderScript را برای درایور فروشنده به دو روش کامپایل کنید:

  1. فراخوانی کامپایلر RenderScript مختص فروشنده در /vendor/bin/ (روش ترجیحی کامپایل GPU). مشابه با دیگر واحدهای درایور، باینری گردآورنده فروشنده نمی‌تواند به هیچ کتابخانه سیستمی که در فهرست کتابخانه‌های RenderScript دردسترس فروشندگان نیست وابسته باشد.
  2. ‫bcc سیستم را با /system/bin/bcc که توسط فروشنده ارائه شده است فراخوانی کنید؛ bcc plugin؛ این افزایه نمی‌تواند به هیچ کتابخانه سیستمی که در فهرست کتابخانه‌های RenderScript دردسترس فروشندگان نیست وابسته باشد.

اگر فروشنده bcc plugin نیاز دارد در تدوین CPU مداخله کند و وابستگی آن به libLLVM.so به‌راحتی قابل‌حذف نیست، فروشنده باید bcc (و همه وابستگی‌های غیر LL-NDK، ازجمله libLLVM.so، libbcc.so) را در بخش /vendor کپی کند.

علاوه‌براین، فروشندگان باید تغییرات زیر را انجام دهند:

شکل ۷. تغییرات در درایور فروشنده.

  1. ‫libclcore.bc را در پارتیشن /vendor کپی کنید. این کار باعث می‌شود libclcore.bc، libLLVM.so، و libbcc.so همگام‌سازی شوند.
  2. با تنظیم RsdCpuScriptImpl::BCC_EXE_PATH از پیاده‌سازی RS HAL، مسیر فایل اجرایی bcc را تغییر دهید.

خط‌مشی SELinux

خط‌مشی SELinux هم بر درایور و هم بر فایل‌های اجرایی کامپایلر تأثیر می‌گذارد. همه واحدهای راه‌انداز باید در file_contexts دستگاه با برچسب same_process_hal_file مشخص شوند. برای مثال:

/vendor/lib(64)?/libRSDriver_EXAMPLE\.so     u:object_r:same_process_hal_file:s0

برنامه اجرایی کامپایلر باید بتواند توسط فرایند برنامه فراخوانی شود، همان‌طور که نسخه فروشنده bcc (/vendor/bin/bcc) می‌تواند. برای مثال:

device/vendor_foo/device_bar/sepolicy/file_contexts:
/vendor/bin/bcc                    u:object_r:same_process_hal_file:s0

دستگاه‌های قدیمی

دستگاه‌های قدیمی دستگاه‌هایی هستند که شرایط زیر را برآورده می‌کنند:

  1. ‫PRODUCT_SHIPPING_API_LEVEL کمتر از ۲۶ است.
  2. ‫PRODUCT_FULL_TREBLE_OVERRIDE تعریف نشده است.

برای دستگاه‌های قدیمی، محدودیت‌ها هنگام ارتقا به Android 8.0 و بالاتر اعمال نمی‌شوند، یعنی درایورها می‌توانند همچنان به کتابخانه‌ها در /system/lib[64] پیوند دهند. بااین‌حال، به‌دلیل تغییر معماری مربوط به OVERRIDE_RS_DRIVER، android.hardware.renderscript@1.0-impl باید در بخش /vendor نصب شود؛ درغیراین‌صورت، زمان اجرای RenderScript مجبور می‌شود به مسیر CPU برگردد.

برای اطلاعات درباره انگیزه منسوخ شدن Renderscript، به «وبلاگ توسعه‌دهندگان Android» مراجعه کنید: محاسبه واحد پردازش گرافیکی Android در آینده. اطلاعات منبع برای این منسوخ‌سازی شامل موارد زیر است: