קצב רענון מרובים

ב-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 DisplayManager sets 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.

אפשרויות למפתחים

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