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

ב-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]
פונקציית קריאה חוזרת חדשה ש-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.

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

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