SurfaceFlinger ו-WindowManager

‏SurfaceFlinger מקבל מאגרים, יוצר מאגרים ושולח אותם למסך. WindowManager מספק ל-SurfaceFlinger מאגרים ומטא-נתונים של חלונות, שבהם SurfaceFlinger משתמש כדי ליצור קומפוזיציה של משטחים במסך.

SurfaceFlinger

SurfaceFlinger יכול לקבל מאגרי נתונים זמניים בשתי דרכים: דרך BufferQueue ו-SurfaceControl, או דרך ASurfaceControl.

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

ב-Android 10 נוספה ASurfaceControl, שזו דרך נוספת שבה SurfaceFlinger יכול לקבל מאגרים. ASurfaceControl משלבת בין משטח למכונה של SurfaceControl לחבילת עסקה אחת שנשלחת ל-SurfaceFlinger. ASurfaceControl משויך לשכבה, שאפליקציות מעדכנות באמצעות מכונות ASurfaceTransaction. לאחר מכן, האפליקציות מקבלות מידע על המכונות של ASurfaceTransaction באמצעות קריאות חזרה (callbacks) שמעבירות את ASurfaceTransactionStats שמכיל מידע, כמו זמן הנעילה, זמני הרכישה וכו'.

בטבלה הבאה מפורטים פרטים נוספים על ASurfaceControl ועל הרכיבים המשויכים אליו:

רכיב תיאור
ASurfaceControl עטיפה של SurfaceControl שמאפשרת לאפליקציה ליצור מכונות SurfaceControl שתואמות לשכבות במסך.

אפשר ליצור אותו כצאצא של ANativeWindow או כצאצא של מכונה אחרת של ASurfaceControl.
ASurfaceTransaction עטיפה של Transaction שמאפשרת ללקוח לערוך את המאפיינים התיאוריים של שכבה, כמו גיאומטריה, ושולחת את המאגרים המעודכנים אל SurfaceFlinger.
ASurfaceTransactionStats שליחת מידע על עסקאות שהוצגו, כמו זמן הנעילה, זמני הרכישה ומחסום השחרור הקודם, לאפליקציה באמצעות קריאה חוזרת (callback) שנרשמה מראש.

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

כשהמסך נמצא בין רענונים, הוא שולח את האות VSync ל-SurfaceFlinger. האות VSync מציין שאפשר לרענן את המסך בלי קריעה. כש-SurfaceFlinger מקבל את האות VSync, הוא עובר על רשימת השכבות שלו ומחפש מאגרים חדשים. אם SurfaceFlinger מוצא מאגר חדש, הוא רוכש אותו. אם לא, הוא ממשיך להשתמש במאגר שנרכש קודם. SurfaceFlinger תמיד צריך להציג משהו, ולכן הוא שומר על מאגר אחד. אם אף פעם לא נשלחו מאגרי נתונים בשכבה מסוימת, המערכת תתעלם מהשכבה.

אחרי ש-SurfaceFlinger אוסף את כל המאגרים לשכבות הגלויה, הוא שואל את ה-Hardware Composer (HWC) איך צריך לבצע את הרכבת התמונה. אם ה-HWC מסמנים את סוג הרכבת השכבות כהרכב של לקוח, SurfaceFlinger משלבת את השכבות האלה. לאחר מכן, SurfaceFlinger מעביר את מאגר הפלט ל-HWC.

WindowManager

WindowManager שולט באובייקטים מסוג Window, שהם קונטיינרים של אובייקטים מסוג View. אובייקטים מסוג Window תמיד מגובבים על ידי אובייקטים מסוג Surface. WindowManager אחראי על מחזורי חיים, אירועי קלט ומיקוד, כיוון המסך, מעברים, אנימציות, מיקום, טרנספורמציות, סדר Z ועוד הרבה היבטים אחרים של חלון. WindowManager שולח את כל המטא-נתונים של החלון אל SurfaceFlinger, כדי ש-SurfaceFlinger יוכל להשתמש בנתונים האלה כדי ליצור משטחים מורכבים במסך.

לפני סיבוב

שכבות-על רבות של חומרה לא תומכות בכיוון (וגם אם כן, הן צורכות יותר כוח עיבוד). הפתרון הוא לבצע טרנספורמציה של המאגר לפני שהוא מגיע ל-SurfaceFlinger. Android תומך בהצעה לשאילתה (NATIVE_WINDOW_TRANSFORM_HINT) ב-ANativeWindow כדי לייצג את הטרנספורמציה שסביר להניח ש-SurfaceFlinger יחיל על המאגר. מנהלי ה-GL יכולים להשתמש בהצעה הזו כדי לבצע טרנספורמציה מראש של המאגר לפני שהוא מגיע ל-SurfaceFlinger, כך שכשהמאגר מגיע, הוא עובר טרנספורמציה בצורה נכונה.

לדוגמה, כשמקבלים רמז לכיוון של 90 מעלות, יוצרים ומחילים מטריקס על המאגר כדי למנוע ממנו לחרוג מעבר לקצה הדף. כדי לחסוך בחשמל, כדאי לבצע את הפעולה הזו לפני הרוטורציה. לפרטים נוספים, ראו את הממשק ANativeWindow שמוגדר ב-system/core/include/system/window.h.