रीफ़्रेश रेट की अलग-अलग सेटिंग

Android 11 में, एक से ज़्यादा रीफ़्रेश रेट वाले डिवाइसों के लिए सहायता जोड़ी गई है. इस सुविधा के तीन मुख्य कॉम्पोनेंट हैं:

  • android.hardware.graphics.composer@2.4 में, नए HAL API जोड़े गए हैं.
  • अलग-अलग रीफ़्रेश रेट के लिए, डिवाइस के कॉन्फ़िगरेशन को पार्स करने और मनचाहा रीफ़्रेश रेट सेट करने के लिए, प्लैटफ़ॉर्म कोड
  • ऐप्लिकेशन को मनचाहा फ़्रेम रेट सेट करने की अनुमति देने के लिए, नए SDK और NDK API

लागू करना

रीफ़्रेश रेट स्विच करने के लिए, खास सहायता जोड़ी गई है…हमारा सुझाव है कि आप इस वर्शन का इस्तेमाल करें, क्योंकि कंपोज़र HAL के पिछले वर्शन में, रीफ़्रेश रेट स्विच करने की सुविधा सीमित है.

कॉन्फ़िगरेशन ग्रुप

IComposerClient::Attribute में एक नया एट्रिब्यूट, CONFIG_GROUP जोड़ा गया है. इसे 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 के बीच स्विच नहीं किया जा सकता, क्योंकि इससे सिर्फ़ रीफ़्रेश रेट बदलने के बजाय, कॉन्फ़िगरेशन में बदलाव होता है.

कंपोज़र API के अपडेट

getDisplayVsyncPeriod
रीफ़्रेश रेट बदलते समय, बेहतर कंट्रोल और अनुमान लगाने की सुविधा के लिए, getDisplayVsyncPeriod जोड़ा गया है. getDisplayVsyncPeriod से, डिसप्ले के मौजूदा रीफ़्रेश रेट (vsync अवधि के हिसाब से) की जानकारी मिलती है. यह खास तौर पर तब काम आता है, जब रीफ़्रेश रेट के बीच ट्रांज़िशन हो रहा हो. साथ ही, प्लैटफ़ॉर्म को यह तय करने के लिए मौजूदा रीफ़्रेश रेट की ज़रूरत होती है कि अगला फ़्रेम कब शुरू करना है.
setActiveConfigWithConstraints
यह setActiveConfigWithConstraints तरीका, मौजूदा setActiveConfig तरीके का नया एक्सटेंशन है. इससे, कॉन्फ़िगरेशन में होने वाले बदलाव के बारे में ज़्यादा जानकारी मिलती है. बाधाएं, vsyncPeriodChangeConstraints पैरामीटर के तौर पर दी जाती हैं. इनमें ये पैरामीटर शामिल होते हैं.
    desiredTimeNanos
    वह समय जिसके बाद vsync अवधि बदली जा सकती है. इसका मतलब है कि vsync अवधि, इस समय से पहले नहीं बदलनी चाहिए.CLOCK_MONOTONIC यह तब काम आता है, जब प्लैटफ़ॉर्म को रीफ़्रेश रेट में बदलाव की पहले से योजना बनानी हो, लेकिन उसके पास दिखाने के लिए पहले से ही कुछ बफ़र मौजूद हों. प्लैटफ़ॉर्म उन बफ़र को ध्यान में रखते हुए यह समय सेट करता है. साथ ही, यह पक्का करता है कि रीफ़्रेश रेट का ट्रांज़िशन जितना हो सके उतना स्मूद हो.
    seamlessRequired
    अगर इसकी वैल्यू 'सही' है, तो इसका मतलब है कि vsync अवधि में बदलाव, बिना किसी रुकावट के होना चाहिए. साथ ही, इसमें कोई विज़ुअल आर्टफ़ैक्ट नहीं दिखना चाहिए. प्लैटफ़ॉर्म इस फ़्लैग का इस्तेमाल तब करता है, जब कॉन्टेंट में बदलाव की वजह से रीफ़्रेश रेट में बदलाव की ज़रूरत होती है. उदाहरण के लिए, डिवाइस इस्तेमाल में नहीं है और ऐनिमेशन शुरू होता है. इससे, वेंडर को कुछ कॉन्फ़िगरेशन में बदलाव की अनुमति न देने का विकल्प मिलता है. ऐसा तब किया जा सकता है, जब उन बदलावों की वजह से कोई विज़ुअल आर्टफ़ैक्ट दिख सकता है. अगर कॉन्फ़िगरेशन में बिना किसी रुकावट के बदलाव नहीं किया जा सकता और seamlessRequired की वैल्यू true पर सेट है, तो उम्मीद की जाती है कि लागू करने की प्रोसेस, SEAMLESS_NOT_POSSIBLE को रिटर्न कोड के तौर पर दिखाएगी. साथ ही, जब एक ही कॉन्फ़िगरेशन में बिना किसी रुकावट के बदलाव किया जा सकेगा, तब onSeamlessPossible कॉलबैक को कॉल करेगी.

सफलता मिलने पर, लागू करने की प्रोसेस VsyncPeriodChangeTimeline दिखाती है. इससे प्लैटफ़ॉर्म को यह पता चलता है कि रीफ़्रेश रेट में बदलाव कब होगा. newVsyncAppliedTimeNanos पैरामीटर को CLOCK_MONOTONIC में उस समय पर सेट करना ज़रूरी है जब नया डिसप्ले, नए vsync पीरियड पर रीफ़्रेश होना शुरू होगा. desiredTimeNanos के साथ मिलकर, इससे प्लैटफ़ॉर्म को रीफ़्रेश रेट स्विच करने की पहले से योजना बनाने और नए रीफ़्रेश रेट के लिए, ऐप्लिकेशन को पहले से टिक करना शुरू करने की अनुमति मिलती है. इससे, रीफ़्रेश रेट का ट्रांज़िशन बिना किसी रुकावट के होता है.

कुछ लागू करने की प्रोसेस के लिए, रीफ़्रेश रेट भेजने से पहले, रीफ़्रेश फ़्रेम भेजना ज़रूरी होता है. इसके लिए, HAL में refreshRequired पैरामीटर होता है. इससे यह पता चलता है कि रीफ़्रेश फ़्रेम की ज़रूरत है. साथ ही, refreshTimeNanos से, पहले vsync की जानकारी मिलती है. इसके बाद, रीफ़्रेश फ़्रेम भेजना ज़रूरी होता है.

onVsyncPeriodTimingChanged [कॉलबैक]
यह एक नया कॉलबैक है. HAL इसे कॉल करके, प्लैटफ़ॉर्म को यह बता सकता है कि टाइमलाइन का कोई पैरामीटर बदल गया है. साथ ही, प्लैटफ़ॉर्म को अपनी टाइमलाइन अडजस्ट करनी होगी. उम्मीद की जाती है कि यह कॉलबैक तब कॉल किया जाएगा, जब किसी वजह से पुरानी टाइमलाइन छूट गई हो. ऐसा HAL पर प्रोसेस होने में ज़्यादा समय लगने या रीफ़्रेश फ़्रेम देर से मिलने की वजह से हो सकता है.

प्लैटफ़ॉर्म, रीफ़्रेश रेट बदलने का फ़ैसला कैसे लेता है?

रीफ़्रेश रेट चुनने की प्रोसेस, सिस्टम की इन दो सेवाओं में होती है:

DisplayManager
रीफ़्रेश रेट के लिए हाई लेवल की नीति DisplayManager सेट करता है. यह डिसप्ले का डिफ़ॉल्ट कॉन्फ़िगरेशन सेट करता है. यह कंपोज़र HAL के कॉन्फ़िगरेशन जैसा ही होता है. इसके अलावा, यह रीफ़्रेश रेट के तौर पर चुनने के लिए, कम से कम और ज़्यादा से ज़्यादा वैल्यू की रेंज सेट करता है.SurfaceFlinger
SurfaceFlinger
यह एक कॉन्फ़िगरेशन सेट करके, रीफ़्रेश रेट तय करता है. यह कॉन्फ़िगरेशन, डिफ़ॉल्ट कॉन्फ़िगरेशन वाले कॉन्फ़िगरेशन ग्रुप में ही होता है. साथ ही, इसका रीफ़्रेश रेट, कम से कम और ज़्यादा से ज़्यादा वैल्यू की रेंज में होता है.

नीति तय करने के लिए, Display Manager इन चरणों को पूरा करता है:

  • से, चालू कॉन्फ़िगरेशन की क्वेरी करके, डिफ़ॉल्ट कॉन्फ़िगरेशन आईडी ढूंढता हैSurfaceFlinger
  • सिस्टम की शर्तों को दोहराकर, कम से कम और ज़्यादा से ज़्यादा वैल्यू की रेंज को सीमित करता है
    • रीफ़्रेश रेट की डिफ़ॉल्ट सेटिंग: रीफ़्रेश रेट की डिफ़ॉल्ट वैल्यू R.integer.config_defaultRefreshRate कॉन्फ़िगरेशन ओवरले में सेट की जाती है. इस वैल्यू का इस्तेमाल, ऐनिमेशन और टच इंटरैक्शन के लिए, डिवाइस के स्टैंडर्ड रीफ़्रेश रेट को तय करने के लिए किया जाता है.
    • रीफ़्रेश रेट की पीक सेटिंग: रीफ़्रेश रेट की पीक वैल्यू Settings.System.PEAK_REFRESH_RATE से पढ़ी जाती है. डिवाइस की मौजूदा सेटिंग (जैसे, मेन्यू के किसी विकल्प से) को दिखाने के लिए, रनटाइम में इस वैल्यू को बदला जाता है. डिफ़ॉल्ट वैल्यू, R.integer.config_defaultPeakRefreshRate कॉन्फ़िगरेशन ओवरले में सेट की जाती है.
    • रीफ़्रेश रेट की कम से कम सेटिंग: रीफ़्रेश रेट की कम से कम वैल्यू Settings.System.MIN_REFRESH_RATE से पढ़ी जाती है. डिवाइस की मौजूदा सेटिंग (जैसे, मेन्यू के किसी विकल्प से) को दिखाने के लिए, रनटाइम में इस वैल्यू को बदला जा सकता है. डिफ़ॉल्ट वैल्यू 0 होती है. इसलिए, कम से कम वैल्यू की कोई डिफ़ॉल्ट सेटिंग नहीं होती.
    • ऐप्लिकेशन ने ModeId का अनुरोध किया: ऐप्लिकेशन, 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 है, तो कॉन्फ़िगर किए गए टाइमआउट के लिए, डिसप्ले चालू करने (या एओडी से बाहर निकलने) पर, रीफ़्रेश रेट की डिफ़ॉल्ट वैल्यू का इस्तेमाल किया जाएगा.

फ़्रेम रेट API

फ़्रेम रेट API की मदद से, ऐप्लिकेशन Android प्लैटफ़ॉर्म को अपने मनचाहे फ़्रेम रेट के बारे में बता सकते हैं. यह सुविधा, Android 11 को टारगेट करने वाले ऐप्लिकेशन के लिए उपलब्ध है. फ़्रेम रेट API के बारे में ज़्यादा जानने के लिए, developer.android.com पर डेवलपर दस्तावेज़ देखें.

डेवलपर के लिए सेटिंग और टूल

मेन्यू में, डेवलपर के लिए एक नया विकल्प जोड़ा गया है. इससे, मौजूदा रीफ़्रेश रेट के साथ डिसप्ले पर एक ओवरले टॉगल किया जा सकता है. नया विकल्प, सेटिंग > सिस्टम > डेवलपर के लिए सेटिंग और टूल > रीफ़्रेश रेट दिखाएं में मौजूद है.