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 באמצעות קריאות חוזרות (callback) שמעבירות את ASurfaceTransactionStats שמכיל מידע, כמו זמן נעילה, זמני רכישה וכו'.

בטבלה הבאה מתוארים ASurfaceControl והרכיבים שמשויכים אליו:

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

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

כשהתצוגה נמצאת בין רענונים, היא שולחת את האות VSync ל-SurfaceFlinger. אות ה-VSync מציין שאפשר לרענן את התצוגה בלי שיופיעו בה קווים אופקיים. כש-SurfaceFlinger מקבל את אות ה-VSync, הוא עובר על רשימת השכבות שלו ומחפש מאגרי נתונים זמניים חדשים. אם נמצא מאגר חדש, SurfaceFlinger מקבל את המאגר. אם לא, הוא ממשיך להשתמש במאגר שהתקבל קודם. ‫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.