RenderScript היא מסגרת להרצת משימות עתירות חישוב בביצועים גבוהים ב-Android. הוא מיועד לשימוש עם חישוב מקביל לנתונים, אבל יכול להועיל גם לעומסי עבודה סדרתיים. סביבת זמן הריצה של RenderScript מבצעת עבודה במקביל בין המעבדים שזמינים במכשיר, כמו מעבדי CPU מרובי ליבות ומעבדי GPU, וכך מאפשרת למפתחים להתמקד בביטוי אלגוריתמים במקום בתזמון עבודה. RenderScript שימושי במיוחד לאפליקציות שמבצעות עיבוד תמונה, צילום חישובי או ראייה ממוחשבת.
במכשירים עם Android 8.0 ואילך נעשה שימוש במסגרת RenderScript הבאה וב-HALs של הספקים:

איור 1. קוד ספק שמקשר לספריות פנימיות.
ההבדלים מ-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 עבור HALs באותו תהליך או VNDK-SP) שזמינות לקוד של ספקים שאפשר לקשר אליהן. בנוסף, מפורטות בו ספריות נוספות שלא קשורות ל-RenderScript, אבל מסופקות גם לקוד הספק.
הרשימה הבאה של ספריות עשויה להיות שונה בין גרסאות Android, אבל היא קבועה לגרסת Android ספציפית. כדי לראות רשימה עדכנית של הספריות הזמינות, אפשר לעיין ב/system/etc/ld.config.txt
.
ספריות RenderScript | ספריות שאינן RenderScript |
---|---|
|
|
הגדרת מרחב שמות של Linker
ההגבלה על הקישור שמונעת שימוש בספריות שלא נמצאות ב-VNDK-SP על ידי קוד הספק נאכפת בזמן הריצה באמצעות מרחב השמות של המקשר. (פרטים נוספים זמינים במצגת VNDK Design).
במכשיר עם Android מגרסה 8.0 ואילך, כל ה-HALs של אותו תהליך (SP-HALs)
למעט RenderScript נטענים בתוך מרחב השמות של ה-linker
sphal
. RenderScript נטען למרחב השמות הספציפי ל-RenderScript rs
, מיקום שמאפשר אכיפה קצת פחות מחמירה של ספריות RenderScript. הטמעת ה-RS צריכה לטעון את הביטקוד המהודר, ולכן /data/*/*.so
נוסף לנתיב של מרחב השמות rs
(אסור ל-SP-HAL אחרים לטעון ספריות ממחיצת הנתונים).
בנוסף, מרחב השמות rs
מאפשר יותר ספריות מאשר מרחבי שמות אחרים. libmediandk.so
ו-libft2.so
חשופים למרחב השמות rs
כי ל-libRS_internal.so
יש תלות פנימית בספריות האלה.

איור 2. הגדרת מרחב שמות עבור הכלי לקישור.
טעינת נהגים
נתיב חלופי של המעבד (CPU)
בהתאם לקיום של RS_CONTEXT_LOW_LATENCY
ביט כשיוצרים הקשר RS, נבחר נתיב CPU או GPU. כשבוחרים בנתיב של המעבד, libRS_internal.so
(ההטמעה הראשית של מסגרת ה-RS) מdlopen
תקשרת ישירות ממרחב השמות של מקשר ברירת המחדל, שבו מסופקות ספריות ה-RS של גרסת הפלטפורמה.
היישום של RS HAL מהספק לא נמצא בשימוש בכלל כשמשתמשים בנתיב חלופי של CPU, ואובייקט RsContext
נוצר עם mVendorDriverName
null. הערך של libRSDriver.so
הוא (כברירת מחדל) dlopen
, וספריית מנהל ההתקן נטענת ממרחב השמות default
כי גם המתקשר (libRS_internal.so
) נטען במרחב השמות default
.

איור 3. נתיב חלופי של המעבד (CPU).
נתיב ה-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
. רכיב ה-HAL של RS
אז dlopen
s libRS_internal.so
במרחב שמות אחר של linker שנקרא rs
.
ספקים יכולים לספק מנהל התקן משלהם של RS על ידי הגדרת הדגל של זמן הבנייה
OVERRIDE_RS_DRIVER
, שמוטמע ביישום של RS HAL
(hardware/interfaces/renderscript/1.0/default/Context.cpp
). שם מנהל ההתקן הזה dlopen
ed עבור הקשר של RS לנתיב של ה-GPU.
היצירה של אובייקט RsContext
מוקצית להטמעה של RS HAL. רכיב ה-HAL מבצע קריאה חוזרת למסגרת ה-RS באמצעות הפונקציה rsContextCreateVendor()
עם שם הדרייבר שבו רוצים להשתמש כארגומנט. לאחר מכן, מסגרת ה-RS טוענת את מנהל ההתקן שצוין כשמאותחלת הפונקציה RsContext
. במקרה הזה, ספריית מנהלי ההתקנים נטענת למרחב השמות rs
כי האובייקט RsContext
נוצר בתוך מרחב השמות rs
ו-/vendor/lib
נמצא בנתיב החיפוש של מרחב השמות.

איור 4. נתיב חלופי של GPU.
במעבר ממרחב השמות default
למרחב השמות sphal
, נעשה שימוש בפונקציה android_load_sphal_library()
כדי להורות ל-linker הדינמי לטעון את הספרייה -impl.so
ממרחב השמות sphal
.libhidltransport.so
כשעוברים ממרחב השמות 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 plugin
היא ספרייה שסופקה על ידי ספק ונטענה למהדר bcc
. מכיוון ש-bcc
הוא תהליך מערכת בספריית /system/bin
, אפשר להתייחס לספריית bcc plugin
כאל SP-HAL (כלומר, HAL של ספק שאפשר לטעון ישירות לתהליך המערכת בלי להשתמש ב-binder). בתור SP-HAL, ספריית bcc-plugin
:
- אי אפשר לקשר לספריות שמבוססות על מסגרות בלבד, כמו
libLLVM.so
. - אפשר לקשר רק לספריות VNDK-SP שזמינות לספק.
ההגבלה הזו נאכפת על ידי טעינת bcc plugin
למרחב השמות sphal
באמצעות הפונקציה android_sphal_load_library()
. בגרסאות קודמות של Android, שם הפלאגין צוין באמצעות האפשרות -load
והספרייה נטענה באמצעות הפקודה הפשוטה dlopen()
על ידי libLLVM.so
. ב-Android מגרסה 8.0 ואילך, האפשרות הזו מצוינת ב--plugin
והספרייה נטענת ישירות על ידי bcc
עצמו. האפשרות הזו מאפשרת להגדיר נתיב לא ספציפי ל-Android לפרויקט הקוד הפתוח LLVM.

איור 5. טעינת הפלאגין של bcc, Android מגרסה 7.x ומטה.

איור 6. טעינת התוסף bcc, Android 8.0 ומעלה.
נתיבי חיפוש של 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 ואילך, צריך לפעול לפי כללים ספציפיים (שנאכפים באמצעות neverallows
) כשמסמנים קבצים נוספים במחיצה vendor
:
-
vendor_file
חייבת להיות התווית שמוגדרת כברירת מחדל לכל הקבצים במחיצהvendor
. מדיניות הפלטפורמה מחייבת זאת כדי לגשת להטמעות של HAL passthrough. - לכל
exec_types
חדש שנוסף במחיצהvendor
דרך ספק SEPolicy צריך להיות מאפייןvendor_file_type
. האכיפה מתבצעת באמצעותneverallows
. - כדי למנוע התנגשויות עם עדכונים עתידיים של פלטפורמות או מסגרות, אל תתנו תוויות לקבצים אחרים מלבד
exec_types
במחיצהvendor
. - כל יחסי התלות של הספרייה עבור HALs באותו תהליך שזוהו ב-AOSP צריכים להיות מסומנים בתווית
same_process_hal_file
.
פרטים על מדיניות SELinux זמינים במאמר בנושא Security-Enhanced Linux ב-Android.
תאימות ABI לביטקוד
אם לא נוספים ממשקי API חדשים, כלומר לא מתבצע עדכון של גרסת HAL, מסגרות ה-RS ימשיכו להשתמש במנהל ההתקן הקיים של ה-GPU (HAL 1.0).
במקרה של שינויים קלים ב-HAL (HAL 1.1) שלא משפיעים על bitcode, המסגרות צריכות לחזור לשימוש ב-CPU עבור ממשקי ה-API החדשים האלה ולהמשיך להשתמש במנהל ההתקן של GPU (HAL 1.0) במקומות אחרים.
במקרה של שינויים משמעותיים ב-HAL (גרסה HAL 2.0) שמשפיעים על הידור או קישור של bitcode, כדאי שמסגרות RS לא יטענו מנהלי התקנים של GPU שסופקו על ידי הספק, ובמקום זאת ישתמשו בנתיב CPU או Vulkan להאצה.
השימוש בביטקוד של RenderScript מתבצע בשלושה שלבים:
שלב | פרטים |
---|---|
הידור |
|
קישור |
|
טעינה |
|
בנוסף ל-HAL, ממשקי API של זמן ריצה והסמלים המיוצאים הם גם ממשקים. הממשקים לא השתנו מאז Android 7.0 (API 24) ואין תוכניות מיידיות לשנות אותם ב-Android 8.0 ואילך. עם זאת, אם הממשק משתנה, גם גרסת ה-HAL תגדל.
הטמעות של ספקים
ב-Android מגרסה 8.0 ואילך, כדי שמנהל ההתקן של ה-GPU יפעל בצורה תקינה, צריך לבצע כמה שינויים במנהל ההתקן של ה-GPU.
מודולים של דרייברים
- מודולים של מנהלי התקנים לא יכולים להיות תלויים בספריות מערכת שלא מופיעות ברשימה.
- הדרייבר חייב לספק
android.hardware.renderscript@1.0-impl_{NAME}
משלו, או להצהיר על הטמעה של ברירת המחדלandroid.hardware.renderscript@1.0-impl
כתלות שלו. - ההטמעה של CPU
libRSDriver.so
היא דוגמה טובה להסרת תלות שאינה VNDK-SP.
קומפיילר של ביטקוד
יש שתי דרכים לקומפילציה של קוד ביניים של RenderScript עבור מנהל ההתקן של הספק:
- הפעלת מהדר RenderScript ספציפי לספק ב-
/vendor/bin/
(השיטה המועדפת למהדר GPU). בדומה למודולים אחרים של מנהלי התקנים, קובץ הבינארי של מהדר הספק לא יכול להיות תלוי בספריית מערכת שלא מופיעה ברשימה של ספריות RenderScript שזמינות לספקים. - הפעלת מערכת ה-BCC:
/system/bin/bcc
עםbcc plugin
שסופק על ידי הספק; הפלאגין הזה לא יכול להיות תלוי בספריית מערכת שלא נמצאת ברשימה של ספריות RenderScript שזמינות לספקים.
אם הספק bcc plugin
צריך להתערב בהידור של המעבד והתלות שלו ב-libLLVM.so
לא ניתנת להסרה בקלות, הספק צריך להעתיק את bcc
(ואת כל התלויות שאינן LL-NDK, כולל libLLVM.so
, libbcc.so
) למחיצה /vendor
.
בנוסף, ספקים צריכים לבצע את השינויים הבאים:

איור 7. שינויים במנהל ההתקן של הספק.
- העתקת
libclcore.bc
למחיצה/vendor
. כך מוודאים ש-libclcore.bc
,libLLVM.so
ו-libbcc.so
מסונכרנים. - כדי לשנות את הנתיב לקובץ ההרצה
bcc
, צריך להגדיר אתRsdCpuScriptImpl::BCC_EXE_PATH
מההטמעה של RS HAL.
מדיניות SELinux
מדיניות SELinux משפיעה גם על מנהל ההתקן וגם על קובצי ההפעלה של הקומפיילר. כל מודולי הדרייבר צריכים להיות מסומנים בתווית same_process_hal_file
ב-file_contexts
של המכשיר. לדוגמה:
/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
מכשירים מדור קודם
מכשירים מדור קודם הם מכשירים שעומדים בתנאים הבאים:
- הערך של PRODUCT_SHIPPING_API_LEVEL נמוך מ-26.
- הערך PRODUCT_FULL_TREBLE_OVERRIDE לא מוגדר.
במכשירים מדור קודם, ההגבלות לא נאכפות כשמשדרגים ל-Android מגרסה 8.0 ואילך, כלומר מנהלי ההתקנים יכולים להמשיך לקשר לספריות ב-/system/lib[64]
. עם זאת, בגלל השינוי בארכיטקטורה שקשור ל-OVERRIDE_RS_DRIVER
, צריך להתקין את android.hardware.renderscript@1.0-impl
במחיצה /vendor
. אם לא עושים את זה, זמן הריצה של RenderScript יחזור לנתיב של יחידת העיבוד המרכזית (CPU).
מידע על הסיבות להוצאה משימוש של Renderscript זמין בבלוג של Android Developers: Android GPU Compute Going Forward. פרטי המשאב לגבי הוצאה משימוש כוללים את הפרטים הבאים:
- העברה מ-RenderScript
- RenderScriptMigration Sample
- Intrinsics Replacement Toolkit README
- Intrinsics ReplacementToolkit.kt