renderScript

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

מכשירים עם Android מגרסה 8.0 ואילך משתמשים ב-RenderScript הבא HALs של framework ו-HAL של ספק:

איור 1. קוד ספק שמקשר ל-libs פנימיים.

ההבדלים בין RenderScript ב-Android 7.x ומטה כוללים:

  • שני מופעים של libs פנימיים ב-RenderScript. קבוצה אחת היא עבור נתיב החלופי של ה-CPU הוא ישירות ב-/system/lib. השני מוגדר לנתיב GPU ומקורו ב-/system/lib/vndk-sp.
  • קישורים פנימיים של RSD ב-/system/lib נבנים כחלק הפלטפורמה והם מתעדכנים במהלך השדרוג של system.img. לעומת זאת, libs ב-/system/lib/vndk-sp נבנו עבור הספק מעודכן כאשר system.img משודרג (בזמן שניתן לעדכן אותם לצורך תיקון אבטחה, ה-ABI שלהם נשאר ללא שינוי).
  • קוד הספק (RS HAL, מנהל התקן RS וה-bcc plugin) הם מקושר ל-libs הפנימיים של RenderScript שנמצאים בכתובת /system/lib/vndk-sp. הם לא יכולים לקשר ל-libs ב- /system/lib כי lib בספרייה הזו נבנו עבור פלטפורמה אחרת, ולכן ייתכן שלא יתאימו לקוד הספק (כלומר, סמלים ). אם תעשו זאת, יהיה בלתי אפשרי להשתמש ב-OTA עם מסגרת בלבד.

עיצוב

הקטעים הבאים מפרטים את העיצוב של RenderScript ב-Android 8.0 ואילך.

קישורים של RenderScript זמינים לספקים

בקטע הזה רשומים מילות המפתח (libs) של RenderScript (שנקראות 'Vendor NDK' לתהליך זהה (Same-Process) HAL או 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

הגדרת מרחב השמות של מקשר

הגבלת הקישור שמונעת שימוש ב-libs שלא נמצאים ב-VNDK-SP קוד הספק נאכף בזמן הריצה באמצעות מרחב השמות המקשר. (לפרטים, לעיון בעיצוב VNDK מצגת.)

במכשיר עם Android מגרסה 8.0 ואילך, כל המעבדים מסוג Same-Process HALs (SP-HAL) חוץ מ-RenderScript נטענים בתוך מרחב השמות של המקשר sphal. RenderScript נטען בקובץ ה-RenderScript הספציפי מרחב השמות rs, מיקום שבו אפשר להשתמש אכיפה של RenderScript libs. כי צריך לטעון את הטמעת ה-RS קוד הביטקוד המורכב, /data/*/*.so, מתווסף לנתיב של מרחב השמות rs (שירותי SP-HAL אחרים אינם מורשים לטעון libs חלוקת נתונים).

בנוסף, מרחב השמות rs מאפשר יותר קישורים ממה שצוין ל- לפי מרחבי שמות אחרים. libmediandk.so ו-libft2.so נחשפו למרחב השמות rs כי ל-libRS_internal.so יש תלות פנימית בספריות האלה.

איור 2. הגדרת מרחב שמות לקישור.

טעינת נהגים

נתיב חלופי של מעבד (CPU)

בהתאם לקיומו של הביט RS_CONTEXT_LOW_LATENCY כשיוצרים הקשר RS, נבחר נתיב ה-CPU או ה-GPU. כאשר נבחר נתיב המעבד (CPU), libRS_internal.so (ההטמעה הראשית של ה-framework של RS) dlopen ישירות מהמקשר המוגדר כברירת מחדל מרחב שמות שבו סופקה גרסת הפלטפורמה של RSA.

לא נעשה בכלל שימוש בהטמעת RS HAL של הספק כשהמעבד נעשה שימוש בנתיב החלופי, ואובייקט RsContext נוצר עם null mVendorDriverName. 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 RSD HAL ואז dlopen libRS_internal.so מרחב שמות של מקשר בשם rs.

ספקים יכולים לספק מנהל התקן RS משלהם על ידי הגדרת התכונה הניסיונית 'זמן build' OVERRIDE_RS_DRIVER, שמוטמע ב-RS HAL יישום (hardware/interfaces/renderscript/1.0/default/Context.cpp). הזה לאחר מכן, שם מנהל ההתקן מקבל dlopen עבור ההקשר של ה-RS בנתיב ה-GPU.

יצירת האובייקט RsContext מועברת ל-RS HAL יישום בפועל. פרוטוקול HAL מבצע קריאה חוזרת ל-framework של RSD באמצעות rsContextCreateVendor() עם שם הנהג/ת כארגומנט. לאחר מכן, מסגרת ה-RS טוענת את מנהל ההתקן שצוין כאשר RsContext הופעל. במקרה הזה, ספריית הנהגים נטען למרחב השמות של rs כי RsContext נוצר בתוך מרחב השמות rs. /vendor/lib נמצא בנתיב החיפוש של מרחב השמות.

איור 4. נתיב חלופי של 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 plugin היא ספרייה שסופקה על ידי ספק, נטענת מהדר (bcc). כי bcc הוא תהליך מערכת ספריית /system/bin, הספרייה bcc plugin יכולה להיות נחשב כ-SP-HAL (כלומר, HAL של ספק שניתן לטעון ישירות במערכת שלא מקשרת ביניהם). בתור SP-HAL, ספרייה של bcc-plugin:

  • לא ניתן לקשר לספריות של framework בלבד כמו libLLVM.so
  • הקישור יכול לקשר רק לספריות VNDK-SP שזמינות לספק.

ההגבלה הזו נאכפת על ידי טעינת bcc plugin אל מרחב השמות sphal שמשתמש ברכיב android_sphal_load_library(). בגרסאות קודמות של Android, שם הפלאגין צוין באמצעות האפשרות -load וגם הליב נטען באמצעות הפקודה dlopen() הפשוטה של libLLVM.so. ב-Android מגרסה 8.0 ואילך, הדבר מצוין האפשרות -plugin וה-lib נטען ישירות על ידי bcc עצמו. אם בוחרים באפשרות הזו, נתיב לא ספציפי ל-Android בפרויקט של קוד פתוח ב-LLVM.

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



איור 6. מתבצעת טעינה של הפלאגין 'עותק מוסתר', Android מגרסה 8.0 ואילך.

נתיבי חיפוש של ld.mc

כשמריצים את הפקודה ld.mc, חלק מפריטי ה-lib של זמן הריצה של RS ניתנים כקלט למנגנון לקישור. ה-bitcode של ה-RS מהאפליקציה מקושר אל ה-libs של סביבת זמן הריצה וכשהביטקוד שהומר נטען לתהליך אפליקציה, libs בסביבת זמן הריצה מקושרים שוב באופן דינמי מהביטקוד שהומר.

כללי זמן הריצה כוללים:

  • libcompiler_rt.so
  • libm.so
  • libc.so
  • מנהל התקן RS (libRSDriver.so או OVERRIDE_RS_DRIVER)

כשטוענים את קטע הקוד שעבר הידור לתהליך האפליקציה, צריך לספק את אותו קוד אימות שהיו בשימוש על ידי ld.mc. אחרת, קטע הקוד שעבר הידור ייתכן שלא ימצא סמל שהיה זמין כשביצעתם קישור.

כדי לעשות זאת, ה-framework של RSD משתמש בנתיבי חיפוש שונים של ה-libs של זמן הריצה כאשר מריצים את ld.mc, בהתאם למסגרת ה-RS עצמה נטען מ-/system/lib או מ-/system/lib/vndk-sp. אפשר לקבוע זאת לפי הכתובת של סמל שרירותי של RS framework lib ומשתמשים ב-dladdr() כדי למפות את נתיב הקובץ אל את הכתובת.

מדיניות SELinux

כתוצאה משינויים במדיניות SELinux ב-Android 8.0 ואילך, לציית לכללים ספציפיים (הנאכפים דרך neverallows) כאשר תיוג קבצים נוספים במחיצה vendor:

  • vendor_file חייבת להיות תווית ברירת המחדל בכל הקבצים ב- מחיצה vendor. לפי מדיניות הפלטפורמה, צריך את זה כדי הטמעת פרוטוקול HAL של העברה.
  • כל ערכי exec_types החדשים נוספו במחיצה vendor דרך SEPolicy של הספק, חייב להיות מאפיין vendor_file_type. המדיניות הזו נאכפת דרך neverallows.
  • כדי למנוע התנגשויות עם עדכונים עתידיים של פלטפורמה או framework, מומלץ לא להוסיף תוויות קבצים אחרים מלבד exec_types במחיצה vendor.
  • לכל יחסי התלות של ספריות עבור HAL של תהליך שמזוהה על ידי AOSP צריך להיות מתויג בתור same_process_hal_file.

פרטים נוספים על המדיניות של SELinux זמינים כאן Linux עם שיפור אבטחה ב-Android.

תאימות ABI לביטקוד

אם לא יתווספו ממשקי API חדשים, כלומר לא תהיה תמיכה בגרסת HAL, של frameworks של RS ימשיך להשתמש במנהל התקן ה-GPU (HAL 1.0) הקיים.

במקרה של שינויי HAL קלים (HAL 1.1) שלא משפיעים על סיביות קוד, ה-frameworks צריך החלופה לשימוש במעבד (CPU) בממשקי ה-API החדשים שנוספו, וממשיכים להשתמש במנהל התקן GPU (HAL 1.0). במקום אחר.

לשינויים משמעותיים ב-HAL (HAL 2.0) שמשפיעים על הידור/קישור של קוד ביטים, RS על frameworks לבחור שלא לטעון מנהלי התקנים של GPU שסופקו על ידי הספק, ובמקום זאת להשתמש במעבד (CPU) או בנתיב Vulkan לצורך האצה.

השימוש ב-bitcode של RenderScript מתרחשת בשלושה שלבים:

שלב פרטים
הידור
  • קוד סיביות (bc.) הקלט של bcc חייב להיות פורמט ביטקוד אחד (LLVM 3.2) והפורמט bcc חייבים להיות אחורה תואמים לאפליקציות קיימות (מדור קודם).
  • עם זאת, המטא-נתונים ב- .bc עשויים להשתנות (יכול להיות שבסביבת זמן ריצה חדשה פונקציות, למשל קביעת הקצאה ∓ פונקציות מתמטיות, פונקציות מתמטיות וכו'). חלק מהפונקציות של סביבת זמן הריצה נמצאים ב-libclcore.bc, חלק מהן גרים ב-LibRSDriver או ספק שווה ערך של ספק.
  • פונקציות חדשות של סביבת זמן ריצה או שינויים במטא-נתונים שעלולים לגרום נזק ארוך מדי ברמת ה-API של קוד ה-bitcode. מאחר שמנהלי ההתקנים של הספקים לא יוכלו לקבל אותו, יש להגדיל גם את גרסת ה-HAL.
  • לספקים יכולים להיות מהדרים משלהם, אבל המסקנות או הדרישות עבור bcc יחולו גם על מהדרים האלה.
קישור
  • קובץ ה- .o שעבר הידור יקושר למנהל התקן של הספק, למשל, libRSDriver_foo.so ו-libcompiler_rt.so. המעבד (CPU) הנתיב יקושר אל libRSDriver.so.
  • אם קובץ ה- .o דורש API חדש של זמן ריצה מ-libRSDriver_foo, צריך לעדכן את מנהל ההתקן של הספק כדי לתמוך בו.
  • לספקים מסוימים עשויים להיות מקשרים משלהם, אבל הארגומנט של ld.mc חלים גם עליהם.
טעינה
  • libRSCpuRef טוען את האובייקט המשותף. אם יש בממשק הזה, נדרשת תמיכה בגרסת HAL.
  • ספקים מסתמכים על libRSCpuRef כדי לטעון את הקובץ המשותף או ליישם אותן.

בנוסף ל-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.

מהדר ב-Bitcode

יש שתי דרכים להדרת קוד ביט של RenderScript עבור מנהל התקן של הספק:

  1. הפעלת מהדר (compiler) ספציפי לספק ב-/vendor/bin/ (השיטה המועדפת להדרת GPU). בדומה למודולים אחרים של מנהלי התקנים, הבינארי של מהדר (compiler) של הספק לא יכול להיות תלוי בספריית מערכת כלשהי שלא נמצאת רשימה של libs ב-RenderScript שזמינות לספקים.
  2. הפעלת 'עותק מוסתר של המערכת': /system/bin/bcc עם ספק שסופק על ידי ספק bcc plugin; הפלאגין הזה לא יכול להסתמך על ספריית מערכת כלשהי לא מופיע ברשימה של libs זמינים ב-RenderScript לספקים.

אם הספק bcc plugin צריך להפריע למעבד (CPU) את המידע ואת התלות שלו ב-libLLVM.so שלא ניתן לחרוג ממנו בקלות הוסר, הספק צריך להעתיק את bcc (וכל הקבצים שאינם LL-NDK של יחסי התלות, כולל libLLVM.so, libbcc.so) מחיצה /vendor.

בנוסף, הספקים צריכים לבצע את השינויים הבאים:

איור 7. שינויים במנהל ההתקן של הספק.

  1. העתקת libclcore.bc אל המחיצה /vendor. הזה מבטיח libclcore.bc, libLLVM.so וגם libbcc.so מסונכרנים.
  2. שינוי הנתיב לקובץ ההפעלה 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

חובה לאפשר את הפעלת קובץ ההפעלה של המהדר על ידי תהליך של אפליקציה, כמו גם עותק של עותק הספק בעותק מוסתר (/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 נמוך מ-26.
  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 GPU Compute קדימה. הפרטים של המשאבים להוצאה משימוש כוללים את הפרטים הבאים: