RenderScript

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

دستگاه‌هایی که اندروید ۸.۰ و بالاتر را اجرا می‌کنند از چارچوب RenderScript و HALهای فروشندگان زیر استفاده می‌کنند:

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

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

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

طراحی

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

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

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

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

کتابخانه‌های رندراسکریپت کتابخانه‌های غیر 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 مراجعه کنید.)

در دستگاهی که اندروید ۸.۰ و بالاتر را اجرا می‌کند، همه HALهای Same-Process (SP-HAL) به جز RenderScript در فضای نام linker sphal بارگذاری می‌شوند. RenderScript در فضای نام مختص RenderScript به نام rs بارگذاری می‌شود، مکانی که اجرای کمی آسان‌تر کتابخانه‌های RenderScript را امکان‌پذیر می‌کند. از آنجا که پیاده‌سازی RS نیاز به بارگذاری کد بیتی کامپایل شده دارد، /data/*/*.so به مسیر فضای نام rs اضافه می‌شود (سایر SP-HALها مجاز به بارگذاری کتابخانه‌ها از پارتیشن داده نیستند).

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

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

درایورهای بار

مسیر جایگزین CPU

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

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

شکل ۳. مسیر جایگزین CPU.

مسیر پردازنده گرافیکی

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

فروشندگان می‌توانند با تنظیم پرچم زمان ساخت OVERRIDE_RS_DRIVER که در پیاده‌سازی RS HAL ( hardware/interfaces/renderscript/1.0/default/Context.cpp ) تعبیه شده است، درایور RS خود را ارائه دهند. سپس نام این درایور برای RS context مربوط به مسیر 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 بارگذاری کند، زمانی که lib از فضای نام sphal پیدا/بارگذاری نشود (که همیشه همینطور است زیرا فضای نام sphal مسیر /system/lib/vndk-sp را که libRS_internal.so در آن قرار دارد، جستجو نمی‌کند). با این پیکربندی، یک فراخوانی ساده dlopen() به libRS_internal.so برای انجام انتقال فضای نام کافی است.

بارگذاری افزونه bcc

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

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

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

شکل ۵. بارگذاری افزونه‌ی bcc، اندروید ۷.x و پایین‌تر.



شکل ۶. بارگذاری افزونه‌ی bcc، اندروید ۸.۰ و بالاتر.

مسیرهای جستجو برای 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 در اندروید ۸.۰ و بالاتر، هنگام برچسب‌گذاری فایل‌های اضافی در پارتیشن vendor ، باید قوانین خاصی را رعایت کنید (که از طریق neverallows اعمال می‌شوند):

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

برای جزئیات بیشتر در مورد سیاست SELinux، به بخش «لینوکس با امنیت بهبود یافته در اندروید» مراجعه کنید.

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

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

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

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

مصرف بیت‌کد RenderScript در سه مرحله رخ می‌دهد:

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

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

پیاده‌سازی‌های فروشنده

اندروید ۸.۰ و بالاتر برای عملکرد صحیح درایور GPU نیاز به تغییراتی در درایور GPU دارد.

ماژول‌های درایور

  • ماژول‌های درایور نباید به هیچ کتابخانه سیستمی که در لیست نیستند، وابسته باشند.
  • درایور باید 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 تعریف نشده است.

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

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