ב-Android 11 נוספה תמיכה במכשירים עם כמה קצבי רענון. התכונה הזו כוללת שלושה רכיבים עיקריים:
- ממשקי HAL API חדשים נוספו בגרסה
android.hardware.graphics.composer@2.4. - קוד פלטפורמה לניתוח של הגדרות מכשיר לקצב רענון שונה ולהגדרת קצב הרענון הרצוי
- ממשקי API חדשים של SDK ו-NDK שמאפשרים לאפליקציות להגדיר את קצב הפריימים הרצוי
הטמעה
נוסף תמיכה ייעודית להחלפת קצב רענון ב… מומלץ מאוד להשתמש בגרסה הזו כי בגרסאות קודמות של composer HAL יש תמיכה מוגבלת בהחלפת קצב רענון.
קבוצות הגדרות
מאפיין חדש, CONFIG_GROUP, נוסף ל-IComposerClient::Attribute שאפשר להריץ עליו שאילתות באמצעות getDisplayAttribute_2_4 API. המאפיין הזה מאפשר לספקים לקבץ הגדרות תצוגה. הגדרות באותה קבוצה מאפשרות מעבר חלק ביניהן ברוב המקרים. הפלטפורמה משתמשת בקבוצת ההגדרות כדי להבדיל בין ההגדרות שאפשר לעבור ביניהן, כדי לשנות את קצב הרענון ולא מאפיינים אחרים בהגדרה.
בדוגמה הבאה אפשר לראות את היתרונות של שימוש בקבוצות הגדרות במכשיר שתומך בארבע הגדרות תצוגה:
- 1080p@60Hz
- 1080p@90Hz
- 1080i@72Hz
- 1080i@48Hz
למרות שהמכשיר תומך בקצבי רענון של 48Hz, 60Hz, 72Hz ו-90Hz, המסך פועל במצב אחר, ומעבר מ-60Hz ל-72Hz משנה את הגדרת המסך מ-1080p ל-1080i, וזה לא בהכרח מה שרוצים. הגדרות לקבוצות משתמשים פותרות את הבעיה הזו. אם מקבצים את 60Hz ו-90Hz בקבוצת הגדרות אחת, ואת 48Hz ו-72Hz בקבוצת הגדרות אחרת, הפלטפורמה יודעת שהיא יכולה לעבור בין 60Hz ל-90Hz ובין 48Hz ל-72Hz, אבל לא בין 60Hz ל-72Hz, כי זה יוביל לשינוי בהגדרות ולא רק לשינוי בקצב הרענון.
עדכונים ב-Composer API
- getDisplayVsyncPeriod
- כדי לשפר את השליטה ואת יכולת החיזוי כשמשנים את קצב הרענון, נוספה ההגדרה
getDisplayVsyncPeriod. getDisplayVsyncPeriodמחזירה את קצב הרענון הנוכחי (במונחים של תקופת סנכרון אנכי) שבו המסך פועל. האפשרות הזו שימושית במיוחד כשעוברים בין קצב רענון, והפלטפורמה צריכה את קצב הרענון הנוכחי כדי להחליט מתי להתחיל את הפריים הבא. - setActiveConfigWithConstraints
- ה-method
setActiveConfigWithConstraintsהוא תוסף חדש ל-method הקייםsetActiveConfig, והוא מספק מידע נוסף על שינוי ההגדרה. האילוצים מופיעים כחלק מהפרמטריםvsyncPeriodChangeConstraintsוכוללים את הפרמטרים הבאים. - desiredTimeNanos
- הזמן ב-
CLOCK_MONOTONICשאחריו יכולה להשתנות התקופה של סנכרון אנכי (כלומר, התקופה של סנכרון אנכי לא יכולה להשתנות לפני הזמן הזה). זה שימושי כשהפלטפורמה רוצה לתכנן מראש שינוי בקצב הרענון, אבל כבר יש לה כמה מאגרי נתונים זמניים בתור להצגה. הפלטפורמה מגדירה את הזמן הזה בהתאם כדי להתחשב במרווחי הזמן האלה ולוודא שהמעבר בין קצבי הרענון יהיה חלק ככל האפשר. - seamlessRequired
- אם הערך הוא true, שינוי התקופה של סנכרון אנכי (vsync) חייב להתבצע בצורה חלקה ללא ארטיפקט חזותי בולט. הפלטפורמה משתמשת בדגל הזה כשצריך לשנות את קצב הרענון כתוצאה משינוי בתוכן (לדוגמה, המכשיר לא פעיל ואנימציה מתחילה). כך הספק יכול למנוע שינויים מסוימים בהגדרות, אם הם עלולים לגרום לאפקט חזותי בולט. אם אי אפשר לשנות את ההגדרות בצורה חלקה וערך המשתנה
seamlessRequiredהואtrue, ההטמעה צריכה להחזיר את הערךSEAMLESS_NOT_POSSIBLEכקוד החזרה ולהפעיל את הקריאה החוזרתonSeamlessPossibleהחדשה כשניתן לבצע את אותו שינוי בהגדרות בצורה חלקה. אם ההטמעה מצליחה, מוחזר
VsyncPeriodChangeTimelineשמציין לפלטפורמה מתי צפוי להתרחש השינוי בקצב הרענון.newVsyncAppliedTimeNanosצריך להגדיר את הפרמטרים לזמן ב-CLOCK_MONOTONICשבו התצוגה החדשה תתחיל לרענן במחזור ה-Vsync החדש. הפרמטר הזה, יחד עםdesiredTimeNanos, מאפשר לפלטפורמה לתכנן מראש את המעבר לקצב הרענון החדש ולהתחיל להפעיל את האפליקציות בקצב הרענון החדש מראש. כך מתאפשר מעבר חלק בין קצבי הרענון.ביישומים מסוימים צריך לשלוח מסגרת רענון לפני שאפשר לשלוח את קצב הרענון. לשם כך, ל-HAL יש את הפרמטר
refreshRequiredכדי לציין שצריך לרענן את הפריים, ואת הפרמטרrefreshTimeNanosכדי לציין את הסנכרון האנכי הראשון שבו צריך לשלוח את הפריים לרענון אחריו.- onVsyncPeriodTimingChanged [callback]
- פונקציית callback חדשה ש-HAL יכול לקרוא לה כדי לציין לפלטפורמה שפרמטר מסוים בציר הזמן השתנה, ושהפלטפורמה צריכה להתאים את ציר הזמן שלה. הקריאה החוזרת הזו אמורה להתבצע אם מסיבה כלשהי ציר הזמן הישן לא הופיע בגלל זמן עיבוד ארוך ב-HAL או בגלל רענון מאוחר של הפריים.
איך הפלטפורמה מחליטה לשנות את קצב הרענון?
בחירת קצב הרענון מתבצעת בשני שירותי המערכת הבאים:
- DisplayManager
- The
DisplayManagersets the high level policy around the refresh rate. היא מגדירה את תצורת התצוגה שמוגדרת כברירת מחדל, שהיא זהה לתצורת ה-HAL של ה-Composer. בנוסף, הוא מגדיר טווח של ערכים מינימליים ומקסימליים שמהםSurfaceFlingerיכול לבחור את קצב הרענון. - SurfaceFlinger
- קובעת את קצב הרענון על ידי הגדרת תצורה שנמצאת באותה קבוצת תצורה כמו תצורת ברירת המחדל, וקצב הרענון שלה נמצא בטווח המינימלי/מקסימלי.
כדי לקבוע את המדיניות, המרכז לניהול תצוגה מבצע את השלבים הבאים:
- הפונקציה מוצאת את מזהה הגדרת ברירת המחדל על ידי שליחת שאילתה להגדרה הפעילה מ-
SurfaceFlinger - הגבלת הטווח של ערכי המינימום והמקסימום על ידי חזרה על תנאי המערכת
- הגדרת קצב רענון ברירת המחדל: ערך ברירת המחדל של קצב הרענון מוגדר בשכבת העל של התצורה
R.integer.config_defaultRefreshRate. הערך הזה משמש לקביעת קצב הרענון הרגיל של המכשיר לאנימציות ולאינטראקציות עם מסך המגע. - הגדרה של קצב רענון מרבי: הערך של קצב הרענון המרבי נקרא מ-
Settings.System.PEAK_REFRESH_RATE. הערך הזה משתנה בזמן הריצה כדי לשקף את ההגדרה הנוכחית של המכשיר (למשל, מתוך אפשרות בתפריט). ערך ברירת המחדל מוגדר בשכבת העל של התצורהR.integer.config_defaultPeakRefreshRate. - הגדרה של קצב רענון מינימלי: הערך של קצב הרענון המינימלי נקרא מ-
Settings.System.MIN_REFRESH_RATE. אפשר לשנות את הערך הזה בזמן הריצה כדי לשקף את ההגדרה הנוכחית של המכשיר (למשל, מתוך אפשרות בתפריט). ערך ברירת המחדל הוא 0, כך שאין ערך מינימלי שמוגדר כברירת מחדל. - מזהה מצב שנדרש על ידי האפליקציה: אפליקציות יכולות להגדיר את
WindowManager.LayoutParams.preferredDisplayModeIdכדי לשקף את ההגדרה המועדפת שבה המסך צריך לפעול. ברוב התנאים, הפונקציהDisplayManagerמגדירה את מזהה ברירת המחדל של התצורה בהתאם, ומגדירה את קצב הרענון המינימלי והמקסימלי כך שיתאימו לקצב הרענון של התצורה. - חיסכון בסוללה: קצב הרענון מוגבל ל-60Hz או פחות כשהמכשיר במצב חיסכון בסוללה, שמסומן באמצעות
Settings.Global.LOW_POWER_MODE.
- הגדרת קצב רענון ברירת המחדל: ערך ברירת המחדל של קצב הרענון מוגדר בשכבת העל של התצורה
אחרי ש-DisplayManager מגדיר את המדיניות, SurfaceFlinger מגדיר את קצב הרענון על סמך השכבות הפעילות (שכבות שמעדכנות את המסגרות בתור). אם הבעלים של השכבה מגדיר קצב פריימים, SurfaceFlinger מנסה להגדיר את קצב הרענון למכפלה של הקצב הזה.
לדוגמה, אם בשתי שכבות פעילות מוגדר קצב פריימים של 24 ו-60, SurfaceFlinger יבחר 120Hz אם הוא זמין. אם קצב הרענון הזה לא זמין ל-SurfaceFlinger, הוא ינסה לבחור את קצב הרענון עם השגיאה המינימלית לקצב הפריימים. מידע נוסף מופיע במסמכי התיעוד למפתחים באתר developer.android.com
SurfaceFlinger משתמש בדגלים הבאים כדי לקבוע את קצב הרענון:
ro.surface_flinger.use_content_detection_for_refresh_rate:אם הערך מוגדר, קצב הרענון נקבע על סמך השכבות הפעילות, גם אם לא הוגדר קצב פריימים. SurfaceFlinger שומר על היוריסטיקה שבה הוא מוצא את קצב הפריימים הממוצע שבו השכבה מפרסמת מאגרי נתונים זמניים על ידי בדיקת חותמת הזמן של ההצגה שמצורפת למאגר הנתונים הזמני.-
ro.surface_flinger.set_touch_timer_ms: אם הערך גדול מ-0, קצב הרענון שמוגדר כברירת מחדל ישמש כשהמשתמש יגע במסך למשך הזמן שמוגדר כפסק זמן. ההיוריסטיקה הזו מתבצעת כדי להיות מוכנים עם קצב הרענון שמוגדר כברירת מחדל לאנימציות. -
ro.surface_flinger.set_idle_timer_ms: אם הערך גדול מ-0, קצב הרענון המינימלי ישמש כשלא מתבצעים עדכונים במסך במהלך הזמן הקצוב לתפוגה שהוגדר. -
ro.surface_flinger.set_display_power_timer_ms: אם הערך גדול מ-0, קצב הרענון שמוגדר כברירת מחדל ישמש להפעלת המסך (או ליציאה ממצב תצוגה תמידית) למשך הזמן שהוגדר לטיימאוט.
Frame Rate API
ממשק ה-API של קצב הפריימים מאפשר לאפליקציות להודיע לפלטפורמת Android מהו קצב הפריימים המיועד שלהן, והוא זמין באפליקציות שמטרגטות ל-Android 11. מידע נוסף על Frame Rate API זמין בתיעוד למפתחים בכתובת developer.android.com.
אפשרויות למפתחים
נוספה לתפריט אפשרות חדשה למפתחים שמאפשרת להפעיל שכבת-על בתצוגה עם קצב הרענון הנוכחי. האפשרות החדשה נמצאת בהגדרות > מערכת > אפשרויות למפתחים > הצגת קצב הרענון.