שימוש ב-IPC של קלסר

בדף הזה מתוארים השינויים במנהל התקן של קלסרים ב-Android 8, פרטים על השימוש ב-binder IPC ורשימות של מדיניות SELinux נדרשת.

שינויים במנהל ההתקן של הקישור

החל מגרסת Android 8, מסגרת Android ומכשירי HAL מתקשרים עכשיו עם באמצעות קלסרים. התקשורת הזו מגדילה משמעותית את קלסרים תנועה, Android 8 כולל כמה שיפורים שנועדו לשמור על IPC של קישור מהר. ספקי SoC ויצרני ציוד מקורי צריכים למזג ישירות מהסניפים הרלוונטיים של android-4.4, android-4.9 ואילך kernel/common.

דומיינים מרובים של כלי קישור (הקשרים)

Common-4.4 ואילך, כולל upstream

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

פיזור

Common-4.4 ואילך, כולל upstream

בגרסאות קודמות של Android, כל פיסת נתונים בקריאה ל-binder הועתקה שלוש פעמים:

  • פעם אחת כדי להפוך אותו לסדרה Parcel בתהליך השיחה
  • אחרי שנכנסים למנהל התקן הליבה כדי להעתיק את Parcel אל היעד תהליך דיפוזיה הפוך
  • פעם אחת כדי לבטל את הסדרת Parcel בתהליך היעד

במכשיר Android 8 פיזור-איסוף כדי להפחית את מספר העותקים מ-3 ל-1. במקום ראשית, הסדרת נתונים בParcel נשארת במקור של המודל ופריסת הזיכרון, והנהג מעתיק אותו מיד ליעד תהליך האימות. אחרי שהנתונים נמצאים בתהליך היעד, המבנה והזיכרון זהה ואפשר לקרוא את הנתונים בלי צורך בעותק נוסף.

נעילה פרטנית

Common-4.4 ואילך, כולל upstream

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

הניסיונות הראשוניים לפתור את הבעיה כללו השבתה של המבצע בזמן ומחזיקים את המנעול הגלובלי. אבל זו הייתה יותר פריצה מאשר פתרון אמיתי, ובסופו של דבר נדחה על ידי ה-upstream ונמחק. הניסיונות הבאים שמתמקד בנעילה פרטנית יותר, שגרסה שלה כבר פועלת במכשירי Pixel מאז ינואר 2017. למרות שרוב השינויים האלה היו באופן ציבורי, בוצעו שיפורים משמעותיים בגרסאות הבאות.

אחרי שזיהינו בעיות קלות בהטמעת הנעילה פרטנית, הם פיתחו פתרון משופר עם ארכיטקטורת נעילה שונה, את השינויים בכל הסתעפויות הליבה (kernel) הנפוצות. אנחנו ממשיכים לבדוק לבצע הטמעה במספר גדול של מכשירים שונים, מכיוון שאנחנו לא מודעים עדיין לא טופלו, זהו ההטמעה המומלצת עבור משלוח של מכשירים עם Android 8.

ירושה של עדיפות בזמן אמת

Common-4.4 ו-Common-4.9 (בקרוב)

מנהל ההתקן של הקישור תמיד תומך בירושה בעדיפות גבוהה. בתור הולך וגדל מספר התהליכים ב-Android שפועלים בעדיפות בזמן אמת, בחלק עכשיו הגיוני שאם שרשור בזמן אמת מבצע קריאה ל-Binder, בתהליך הטיפול הזה פועל גם הוא בעדיפות בזמן אמת. שפת תרגום שתומכים בתרחישים כאלה, ב-Android 8 מתבצעת עכשיו ירושה של עדיפות בזמן אמת במנהל הקישורים.

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

שינויים במרחב המשתמשים

Android 8 כולל את כל השינויים במרחב המשתמשים שנדרשים כדי לעבוד עם הגרסה הנוכחית של מנהל התקן binder בליבה המשותפת, למעט חריג אחד: כדי להשבית ירושה של עדיפות בזמן אמת /dev/binder השתמש/ה ב ioctl. בקרת העדיפות שונתה מהפיתוח הבא ירושה לשיטה פרטנית יותר שפועלת לפי מצב קישור (ולא הקשר מסוים). לכן, ה-ioctl לא נמצא בהסתעפות המשותפת של Android אלא נשלחות בליבה (kernel) המשותפת שלנו.

ההשפעה של השינוי הזה היא שירושה של עדיפות בזמן אמת מושבתת על ידי ברירת מחדל עבור כל צומת. צוות הביצועים של Android מצא לאפשר ירושה בעדיפות גבוהה בזמן אמת לכל הצמתים דומיין hwbinder. כדי להשיג את אותו אפקט, בחרו השינוי הזה במרחב המשתמשים.

SHAs לליבות נפוצות

כדי לקבל את השינויים הנדרשים במנהל ההתקן של הקישור, צריך לסנכרן עם SHA המתאים:

  • Common-3.18
    cc8b90c121de ANDROID: binder: לא לבדוק הרשאות prio במהלך השחזור.
  • Common-4.4
    76b376eac7a2 ANDROID: binder: לא צריך לבדוק את ההרשאות ב-Prio במהלך השחזור.
  • Common-4.9
    ecd972d4f9b5 ANDROID: binder: לא לבדוק הרשאות prio במהלך השחזור.

עבודה עם IPC של binder

בעבר, תהליכי ספקים השתמשו בתקשורת בין תהליכים של קלסרים (IPC) כדי לתקשר. ב-Android 8, הצומת של המכשיר /dev/binder הופכת לבלעדית לתהליכי framework, כלומר, תהליכי ספק כבר לא זמינים יכולים לגשת אליו. לתהליכי ספקים יש גישה אל /dev/hwbinder, אבל חייבים להמיר את ממשקי ה-AIDL שלהם כדי להשתמש ב-HIDL. לספקים שרוצים להמשיך באמצעות ממשקי AIDL בין תהליכי ספק, מערכת Android תומכת ב-Binder IPC, שמתואר בהמשך. ב-Android 10, מערכת Stable AIDL מאפשרת את כל סוגי התוכן לשימוש ב-/dev/binder תוך פתרון בעיות היציבות מובטחות HIDL ו-/dev/hwbinder שנפתרו. איך להשתמש בערוץ יציב AIDL, מידע נוסף AIDL ל-HALs.

Vndbinder

ב-Android 8 יש תמיכה בדומיין חדש של binder לשימוש של שירותי ספקים, שיש גישה אליו באמצעות /dev/vndbinder במקום /dev/binder. עם התוספת של /dev/vndbinder, Android כוללת עכשיו את שלושת הסוגים הבאים דומיינים של IPC:

דומיין IPC תיאור
/dev/binder IPC בין תהליכי framework ואפליקציה עם ממשקי AIDL
/dev/hwbinder IPC בין תהליכי framework/ספק עם ממשקי HIDL
IPC בין תהליכי ספק עם ממשקי HIDL
/dev/vndbinder IPC בין תהליכי ספק/ספק באמצעות ממשקי AIDL

כדי ש-/dev/vndbinder יופיע, צריך לוודא שהגדרת הליבה (kernel) הפריט CONFIG_ANDROID_BINDER_DEVICES מוגדר "binder,hwbinder,vndbinder" (זו ברירת המחדל במכשירי Android עצי ליבה נפוצים).

בדרך כלל, תהליכי ספק לא פותחים את מנהל ההתקן של הקישור ישירות, ובמקום זאת קישור לספריית מרחב המשתמשים libbinder, שפותחת את התקן קלסר. מתבצעת הוספה של שיטה עבור ::android::ProcessState() בוחר את מנהל ההתקן של הקישור עבור libbinder. תהליכי הספק קוראים לשיטה הזו לפני שקוראים ל-ProcessState, IPCThreadState, או לפני ביצוע של קריאות כלשהן ב-Binder. שפת תרגום להשתמש, לבצע את הקריאה הבאה אחרי main() של תהליך ספק (לקוח ושרת):

ProcessState::initWithDriver("/dev/vndbinder");

vndservicemanager

בעבר, שירותי binder נרשמו אצל servicemanager, שבו אפשר לאחזר אותם באמצעות תהליכים אחרים. ב-Android 8, האפליקציה servicemanager נמצאת עכשיו בשימוש רק במסגרת ה-framework והאפליקציה ותהליכי ספקים לא יכולים יותר לגשת אליו.

אבל עכשיו שירותי ספקים יכולים להשתמש ב-vndservicemanager, מופע של servicemanager שמשתמש ב-/dev/vndbinder במקום /dev/binder, והוא מבוסס על אותם מקורות כמו מסגרת servicemanager. תהליכי הספק לא צריכים לבצע שינויים לדיבור עם vndservicemanager; כשנפתח תהליך של ספק /dev/vndbinder, חיפושי שירותים עוברים באופן אוטומטי אל vndservicemanager

הקובץ הבינארי vndservicemanager כלול בברירת המחדל של Android makefiles.

מדיניות SELinux

תהליכים של ספקים שרוצים להשתמש בפונקציונליות של קלסר כדי לתקשר איתם זה לזה צריך את הדברים הבאים:

  1. גישה אל /dev/vndbinder.
  2. צריך לקשר את {transfer, call} קטעי הוקים אל תוך vndservicemanager.
  3. binder_call(A, B) עבור כל דומיין ספק א' שרוצה להתקשר בדומיין הספק ב' בממשק של קישור הספק.
  4. הרשאה ל-{add, find} שירותים ב- vndservicemanager.

כדי לעמוד בדרישות 1 ו-2, צריך להשתמש בvndbinder_use() מאקרו:

vndbinder_use(some_vendor_process_domain);

כדי לעמוד בדרישה 3, binder_call(A, B) של הספק תהליכים א' וב' שצריכים לדבר דרך קלסרים יכולים להישאר במקומם צריך לשנות שם.

כדי לעמוד בדרישה 4, יש לבצע שינויים באופן שבו שמות השירותים, תוויות שירות וכללים מטופלים.

לפרטים על SELinux, ראו אבטחה משופרת Linux ב-Android. לפרטים על SELinux ב-Android 8.0, ראו SELinux ל-Android 8.0.

שמות שירותים

בעבר, הספק מעבד שמות שירות רשומים קובץ אחד (service_contexts) ונוספו כללים תואמים לגישה . דוגמה לקובץ service_contexts מ- device/google/marlin/sepolicy:

AtCmdFwd                              u:object_r:atfwd_service:s0
cneservice                            u:object_r:cne_service:s0
qti.ims.connectionmanagerservice      u:object_r:imscm_service:s0
rcs                                   u:object_r:radio_service:s0
uce                                   u:object_r:uce_service:s0
vendor.qcom.PeripheralManager         u:object_r:per_mgr_service:s0

ב-Android 8, vndservicemanager טוען את במקום זאת, יש קובץ vndservice_contexts. העברה של שירותי ספקים אל vndservicemanager (והם כבר ישנים service_contexts) יש להוסיף את הקובץ החדש קובץ vndservice_contexts.

תוויות שירות

בעבר, תוויות שירות כמו u:object_r:atfwd_service:s0 הוגדרו בקובץ service.te. דוגמה:

type atfwd_service,      service_manager_type;

ב-Android 8, צריך לשנות את הסוג ל- vndservice_manager_type ומעבירים את הכלל אל קובץ vndservice.te. דוגמה:

type atfwd_service,      vndservice_manager_type;

כללים של מנהל השירות

בעבר, כללים העניקו לדומיינים גישה להוספה או לחיפוש של שירותים מאת servicemanager דוגמה:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;

ב-Android 8, כללים כאלה יכולים להישאר בתוקף ולהשתמש באותה כיתה. דוגמה:

allow atfwd atfwd_service:service_manager find;
allow some_vendor_app atfwd_service:service_manager add;