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

ב-Android 11 נוספה תמיכה במכשירים עם כמה קצבי רענון. יש שלושה רכיבים עיקריים לתכונה הזו:

  • ממשקי HAL API חדשים שהוצגו בגרסה android.hardware.graphics.composer@2.4.
  • קוד פלטפורמה לניתוח הגדרות המכשיר לקצב רענון שונה ולהגדרת קצב הרענון הרצוי
  • ממשקי API חדשים של SDK ו-NDK שמאפשרים לאפליקציות להגדיר את קצב הפריימים הרצוי

הטמעה

הוספנו ל-android.hardware.graphics.composer@2.4 HAL תמיכה ייעודית בהחלפת קצב רענון. מומלץ מאוד להשתמש בגרסה הזו, כי לגרסאות קודמות של 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 שבו התצוגה החדשה תתחיל לרענן במרווח החדש של סנכרון אנכי. הנתון הזה, יחד עם desiredTimeNanos, מאפשר לפלטפורמה לתכנן מראש את המעבר לקצב הרענון החדש ולהתחיל לספור את הזמן שנותר לרענון האפליקציות מראש. כך מתאפשר מעבר חלק בין קצבי הרענון.

ביישומים מסוימים צריך לשלוח מסגרת רענון לפני שאפשר לשלוח את קצב הרענון. לשם כך, ל-HAL יש את הפרמטר refreshRequired שמציין שצריך לרענן את הפריים, ואת הפרמטר refreshTimeNanos שמציין את הסנכרון האנכי הראשון שבו צריך לשלוח את הפריים לרענון אחריו.

onVsyncPeriodTimingChanged [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 מגדירה את מזהה ברירת המחדל של התצורה בהתאם, ומגדירה את קצב הרענון המינימלי והמקסימלי כך שיתאים לקצב הרענון של התצורה.
    • חיסכון בסוללה: קצב הרענון מוגבל ל-60 הרץ או פחות כשהמכשיר במצב צריכת חשמל נמוכה, שמסומן באמצעות 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.

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

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