Android 11 (एपीआई लेवल 30) या इसके बाद के वर्शन में, कैश मेमोरी में सेव किए गए ऐप्लिकेशन को फ़्रीज़ करने की सुविधा उपलब्ध है. इस सुविधा से, कैश मेमोरी में सेव की गई प्रोसेस को बैकग्राउंड में चलने से रोका जा सकता है. साथ ही, यह उन ऐप्लिकेशन के संसाधन इस्तेमाल करने की दर को कम करती है जो कैश मेमोरी में सेव होने के बावजूद, बैकग्राउंड में चलते रहते हैं.
कैश मेमोरी में सेव किए गए ऐप्लिकेशन को फ़्रीज़ करने की सुविधा, ऐप्लिकेशन को रैम में सेव रखती है, लेकिन उन्हें सीपीयू से अलग रखती है. अगर Android को लगता है कि किसी ऐप्लिकेशन को बैकग्राउंड में नहीं चलना चाहिए, लेकिन आने वाले समय में उसकी ज़रूरत पड़ सकती है, तो वह उसे बंद करने के बजाय फ़्रीज़ कर देता है. इससे, ऐप्लिकेशन को दोबारा शुरू करने पर, कोल्ड स्टार्ट की समस्या नहीं होती.
Android, कैश मेमोरी में सेव किए गए ऐप्लिकेशन को फ़्रीज़ करने के लिए, उनकी प्रोसेस को फ़्रीज़ किए गए cgroup में माइग्रेट करता है. इससे, कैश मेमोरी में सेव किए गए ऐप्लिकेशन के चालू रहने पर, सीपीयू की खपत कम होती है. ऐप्लिकेशन को फ़्रीज़ करने की सुविधा, सिस्टम कॉन्फ़िगरेशन फ़्लैग या डेवलपर विकल्प का इस्तेमाल करके चालू की जा सकती है.
Android 14 (एपीआई लेवल 34) और इसके बाद के वर्शन में, कैश मेमोरी में सेव किए गए ऐप्लिकेशन को फ़्रीज़ करने की सुविधा में ये बेहतर सुविधाएं शामिल हैं:
- कैश मेमोरी में सेव किए गए ऐप्लिकेशन की प्रोसेस, कैश मेमोरी में सेव होने के 10 सेकंड बाद फ़्रीज़ हो जाती हैं.
- लाइफ़साइकल इवेंट के दौरान, सिस्टम फ़्रीज़ की गई ऐप्लिकेशन प्रोसेस को तुरंत अनफ़्रीज़ कर देता है. इन इवेंट में, इंटेंट पाना, जॉब सेवा शुरू करना या उपयोगकर्ता की किसी गतिविधि को फिर से शुरू करना शामिल है.
ActivityManagerService , ऐप्लिकेशन की सभी प्रोसेस को मैनेज करता है और ऐप्लिकेशन के लाइफ़साइकल से जुड़े फ़ैसले लेता है. CachedAppOptimizer, ऐप्लिकेशन की प्रोसेस को फ़्रीज़ करने के लिए ज़िम्मेदार होता है.
किसी ऐप्लिकेशन की प्रोसेस के फ़्रीज़ होने पर, उसके सभी थ्रेड निलंबित हो जाते हैं. साथ ही, वे अनफ़्रीज़ होने तक सीपीयू का इस्तेमाल नहीं कर पाते. नतीजतन, ऐप्लिकेशन गार्बेज कलेक्शन (जीसी) नहीं कर पाता और मेमोरी ट्रिम इवेंट का जवाब नहीं दे पाता. ज़्यादा जानकारी के लिए, ComponentCallbacks2.onTrimMemory(int) देखें. इसके लिए, Android 14 में यह बदलाव किया गया है:
- बैकग्राउंड में जाने पर,
Activityइंस्टेंस वाले ऐप्लिकेशन कोTRIM_MEMORY_UI_HIDDENकी सूचना तुरंत मिलती है. ऐसे ऐप्लिकेशन जिन्हें यूज़र इंटरफ़ेस (यूआई) की ज़रूरत नहीं होती, जैसे कि फ़ोरग्राउंड सेवा वाले ऐप्लिकेशन, उन्हें मिल सकता हैTRIM_MEMORY_BACKGROUND. अन्य ट्रिम इवेंट डिलीवर नहीं किए जाते, क्योंकि जब ऐप्लिकेशन इन इवेंट के लिए ज़रूरी शर्तें पूरी करते हैं, तो उन्हें फ़्रीज़ कर दिया जाता है. - कैश मेमोरी में सेव होने के कुछ समय बाद, सिस्टम ऐप्लिकेशन रनटाइम से जीसी करने का अनुरोध कर सकता है, ताकि ऐप्लिकेशन को फ़्रीज़ किया जा सके.
- किसी ऐप्लिकेशन की प्रोसेस के फ़्रीज़ होने पर, मेमोरी को कंप्रेस करने के लिए अतिरिक्त चरण पूरे किए जा सकते हैं. जैसे, डर्टी पेजों को बैकअप स्टोरेज में लिखना और एनॉनिमस पेजों को ZRAM में स्वैप करना.
- अगर किसी ऐप्लिकेशन की सभी प्रोसेस फ़्रीज़ हो जाती हैं, तो सिस्टम उस ऐप्लिकेशन के चालू टीसीपी सॉकेट बंद कर देता है. इससे, सॉकेट का सर्वर साइड, टीसीपी कीपअलाइव पिंग नहीं भेज पाता. अगर ऐसा होता, तो डिवाइस का मॉडेम चालू हो जाता.
कैश मेमोरी में सेव किए गए ऐप्लिकेशन की प्रोसेस, तब अनफ़्रीज़ हो जाती हैं, जब उनकी प्रोसेस का स्टेटस, कैश मेमोरी में सेव किए गए स्टेटस से बदलकर, ज़्यादा ज़रूरी स्टेटस पर पहुंच जाता है. Android 14 और इसके बाद के वर्शन में, अनफ़्रीज़ इवेंट को कम करने के लिए, सिस्टम, कॉन्टेक्स्ट-रजिस्टर्ड ब्रॉडकास्ट को तब तक कतार में रखता है, जब तक ऐप्लिकेशन कैश मेमोरी में सेव रहता है. कॉन्टेक्स्ट-रजिस्टर्ड ब्रॉडकास्ट, ऐसे रिसीवर होते हैं जिन्हें कोई ऐप्लिकेशन,
डाइनैमिक तरीके से Context.registerReceiver को कॉल करके रजिस्टर करता है. सिस्टम, कतार में रखे गए इन ब्रॉडकास्ट को, ऐप्लिकेशन के अनफ़्रीज़ होने के बाद ही डिलीवर करता है. इसके उलट, सिस्टम, मेनिफ़ेस्ट में बताए गए ब्रॉडकास्ट को कतार में नहीं रखता.
मेनिफ़ेस्ट में बताए गए ब्रॉडकास्ट, ऐसे रिसीवर होते हैं जिन्हें
AndroidManifest.xml में <receiver> एलिमेंट का इस्तेमाल करके, स्टैटिक तरीके से बताया जाता है. सिस्टम, मेनिफ़ेस्ट में बताए गए ब्रॉडकास्ट को डिलीवर करने के लिए, कैश मेमोरी में सेव किए गए ऐप्लिकेशन को तुरंत अनफ़्रीज़ कर देता है.
सिस्टम की परफ़ॉर्मेंस पर असर
अगर कैश मेमोरी में सेव किए गए ऐप्लिकेशन की प्रोसेस की संख्या, MAX_CACHED_PROCESSES से ज़्यादा है, तो Android, कैश मेमोरी में सेव किए गए ऐसे ऐप्लिकेशन की प्रोसेस को बंद कर देता है जिसका इस्तेमाल हाल ही में नहीं किया गया है. Android 14 या इसके बाद के वर्शन पर काम करने वाले, ज़रूरी शर्तें पूरी करने वाले डिवाइसों पर, MAX_CACHED_PROCESSES को काफ़ी बढ़ा दिया गया है. इससे डिवाइस, रैम में कैश मेमोरी में सेव किए गए ऐप्लिकेशन की ज़्यादा प्रोसेस को बनाए रख सकते हैं.
रैम में ज़्यादा ऐप्लिकेशन कैश मेमोरी में सेव रखने से, कोल्ड स्टार्ट की समस्या 30% तक कम हो जाती है. डिवाइस की कुल रैम के आधार पर, यह कमी बढ़ सकती है. साथ ही, कैश मेमोरी में सेव किए गए ऐप्लिकेशन की वजह से, सीपीयू की खपत कम होती है. इससे बैटरी की बचत होती है.
ऐप्लिकेशन को फ़्रीज़ करने की सुविधा से छूट
कुछ मामलों में, किसी ऐप्लिकेशन की प्रोसेस, कैश मेमोरी में सेव की जा सकती है, लेकिन उसे फ़्रीज़ नहीं किया जा सकता. ये छूट, लागू करने से जुड़ी जानकारी हैं. आने वाले Android वर्शन में, इनमें बदलाव हो सकता है:
- फ़ाइल लॉक: अगर कैश मेमोरी में सेव की गई कोई प्रोसेस, फ़ाइल लॉक रखती है, तो उस लॉक की वजह से, कैश मेमोरी में सेव नहीं की गई अन्य प्रोसेस ब्लॉक हो जाती हैं. ऐसे में, लॉक रखने वाली प्रोसेस को फ़्रीज़ नहीं किया जाता.
BIND_WAIVE_PRIORITYबाइंडिंग: इनकमिंग बाइंडिंग वाली ऐप्लिकेशन प्रोसेस,Context.BIND_WAIVE_PRIORITYका इस्तेमाल करके बनाई गई हैं. इन्हें कैश मेमोरी में सेव किया जा सकता है. हालांकि, इन्हें तब तक फ़्रीज़ नहीं किया जाता, जब तक कनेक्ट किए गए सभी क्लाइंट प्रोसेस भी कैश मेमोरी में सेव नहीं हो जातीं. यह छूट, मल्टी-प्रोसेस ऐप्लिकेशन के लिए है. जैसे, कस्टम टैब का इस्तेमाल करने वाले वेब ब्राउज़र.
ऐप्लिकेशन को फ़्रीज़ करने की सुविधा लागू करना
कैश मेमोरी में सेव किए गए ऐप्लिकेशन को फ़्रीज़ करने की सुविधा, कर्नल cgroup v2 फ़्रीज़र का इस्तेमाल करती है. ज़रूरी शर्तें पूरी करने वाले कर्नल वाले डिवाइसों पर, इसे चालू किया जा सकता है. कैश मेमोरी में सेव किए गए ऐप्लिकेशन को बैकग्राउंड में न चलने दें डेवलपर विकल्प को चालू करें या डिवाइस कॉन्फ़िग फ़्लैग activity_manager_native_boot use_freezer को true पर सेट करें. उदाहरण के लिए:
adb shell device_config put activity_manager_native_boot use_freezer true && adb rebootuse_freezer फ़्लैग को false पर सेट करने या डेवलपर विकल्प को बंद करने पर, फ़्रीज़र बंद हो जाता है. उदाहरण के लिए:
adb shell device_config put activity_manager_native_boot use_freezer false && adb rebootसॉफ़्टवेयर रिलीज़ या अपडेट में, डिवाइस के कॉन्फ़िगरेशन में बदलाव करके, इस सेटिंग को टॉगल किया जा सकता है.
MAX_CACHED_PROCESSES को बदलने के लिए, उदाहरण के लिए, टेस्ट करने के लिए वैल्यू को 1024 पर सेट करने के लिए:
adb shell device_config put activity_manager max_cached_processes 1024
adb shell device_config set_sync_disabled_for_tests persistentMAX_CACHED_PROCESSES को पहले जैसा करने के लिए:
adb shell device_config delete activity_manager max_cached_processes
adb shell device_config set_sync_disabled_for_tests noneऐप्लिकेशन को फ़्रीज़ करने की सुविधा, आधिकारिक एपीआई उपलब्ध नहीं कराती. साथ ही, इसमें रेफ़रंस लागू करने वाला कोई क्लाइंट नहीं होता. हालांकि, यह किसी प्रोसेस को फ़्रीज़ करने के लिए, छिपे हुए सिस्टम एपीआई setProcessFrozen और ग्लोबल तौर पर फ़्रीज़ करने की सुविधा को चालू या बंद करने के लिए, enableFreezer का इस्तेमाल करती है.
कस्टम सुविधाओं को मैनेज करना
कैश मेमोरी में सेव किए गए ऐप्लिकेशन की प्रोसेस से कोई काम नहीं कराया जाता. हालांकि, कुछ ऐप्लिकेशन में कस्टम सुविधाएं हो सकती हैं. ये सुविधाएं, कैश मेमोरी में सेव होने के दौरान भी चलने वाली प्रोसेस की मदद से काम करती हैं. ऐसे ऐप्लिकेशन चलाने वाले डिवाइस पर, ऐप्लिकेशन को फ़्रीज़ करने की सुविधा चालू होने पर, कैश मेमोरी में सेव की गई प्रोसेस फ़्रीज़ हो जाती हैं. इससे, कस्टम सुविधाएं काम नहीं कर पाती हैं.
इससे बचने के लिए, प्रोसेस से कोई काम कराने से पहले, प्रोसेस का स्टेटस बदलकर, कैश मेमोरी में सेव नहीं किया गया स्टेटस पर सेट करें. इस बदलाव से, ऐप्लिकेशन चालू रह पाते हैं. चालू स्टेटस के उदाहरणों में, बाउंड फ़ोरग्राउंड सेवा या फ़ोरग्राउंड स्टेटस शामिल है.
आम तौर पर होने वाली गड़बड़ियां
ऐप्लिकेशन की प्रोसेस के फ़्रीज़ होने पर, प्रोसेस के बीच गलत तरीके से इंटर-प्रोसेस कम्यूनिकेशन (आईपीसी) या टास्क शेड्यूलिंग की वजह से, ऐप्लिकेशन बंद हो सकते हैं या अनचाहा व्यवहार हो सकता है.
फ़्रीज़ की गई प्रोसेस के लिए, सिंक्रोनस बाइंडर ट्रांज़ैक्शन
जब कोई क्लाइंट ऐप्लिकेशन प्रोसेस, फ़्रीज़ की गई सर्वर ऐप्लिकेशन प्रोसेस को सिंक्रोनस बाइंडर ट्रांज़ैक्शन भेजती है, तो सिस्टम, सर्वर ऐप्लिकेशन प्रोसेस को तुरंत बंद कर देता है. इससे, फ़्रीज़ किए गए सर्वर से जवाब का इंतज़ार करते समय, क्लाइंट थ्रेड को हमेशा के लिए ब्लॉक होने से रोका जा सकता है. इसके बाद, क्लाइंट थ्रेड को
RemoteException मिलता है. साथ ही, रजिस्टर किए गए सभी लिसनर
ट्रिगर हो जाते हैं. ज़्यादा जानकारी के लिए, IBinder.linkToDeath देखें.
गड़बड़ी की वजह: आम तौर पर, यह गड़बड़ी क्लाइंट ऐप्लिकेशन में मौजूद किसी बग की वजह से होती है. जब कोई क्लाइंट किसी सेवा से बाइंड होता है, तो सर्वर प्रोसेस, क्लाइंट से बाइंड हो जाती है. साथ ही, क्लाइंट के कैश मेमोरी में सेव होने से पहले, सर्वर प्रोसेस को कैश मेमोरी में सेव होने से रोका जाता है. ज़्यादा जानकारी के लिए,
देखें Context.bindService. हालांकि, क्लाइंट के
Context.unbindService को कॉल करने के बाद, सर्वर प्रोसेस को
कैश मेमोरी में सेव किया जा सकता है और उसे फ़्रीज़ किया जा सकता है. अगर क्लाइंट, अनबाइंड करने के बाद भी, कैश मेमोरी में सेव किए गए
IBinder रेफ़रंस का इस्तेमाल करता है, तो वह फ़्रीज़ की गई प्रोसेस से कम्यूनिकेट कर सकता है.
इस समस्या से बचने के लिए, पक्का करें कि क्लाइंट ऐप्लिकेशन,
Context.unbindService को कॉल करने के तुरंत बाद, IBinder
रेफ़रंस को हटा दें.
एसिंक्रोनस बाइंडर ट्रांज़ैक्शन बफ़र ओवरफ़्लो
जब कोई सर्वर ऐप्लिकेशन प्रोसेस, फ़्रीज़ होने के दौरान एसिंक्रोनस (oneway) बाइंडर ट्रांज़ैक्शन पाती है, तो ट्रांज़ैक्शन को हर प्रोसेस के लिए बफ़र में बफ़र किया जाता है. अगर सर्वर को फ़्रीज़ होने के दौरान, बहुत ज़्यादा एसिंक्रोनस ट्रांज़ैक्शन मिलते हैं, तो बफ़र ओवरफ़्लो हो जाता है. साथ ही, सिस्टम, सर्वर ऐप्लिकेशन प्रोसेस को बंद कर देता है.
बफ़र ओवरफ़्लो से बचने के लिए, ऐसी प्रोसेस को बहुत ज़्यादा एसिंक्रोनस बाइंडर ट्रांज़ैक्शन न भेजें जिन्हें कैश मेमोरी में सेव किया जा सकता है या फ़्रीज़ किया जा सकता है.
अनफ़्रीज़ होने पर, शेड्यूल किए गए टास्क को बार-बार लागू करना
अगर कोई ऐप्लिकेशन, बार-बार होने वाले टास्क को लागू करता है, तो प्रोसेस के फ़्रीज़ होने पर, उन्हें निलंबित कर दिया जाता है. ज़्यादा जानकारी के लिए, ScheduledThreadPoolExecutor.scheduleAtFixedRate
या Timer.scheduleAtFixedRateदेखें. प्रोसेस के अनफ़्रीज़ होने पर, छूटे हुए टास्क को तुरंत और बिना किसी देरी के लागू किया जा सकता है.
ऐप्लिकेशन के अनफ़्रीज़ होने पर, टास्क को तुरंत लागू होने से रोकने के लिए, बैकग्राउंड
टास्क के लिए
scheduleAtFixedRate के बजाय
scheduleWithFixedDelay का इस्तेमाल करें. WorkManager का भी इस्तेमाल किया जा सकता है.
ऐप्लिकेशन को फ़्रीज़ करने की सुविधा की जांच करना और उससे जुड़ी समस्याओं को हल करना
यह पुष्टि करने के लिए कि ऐप्लिकेशन को फ़्रीज़ करने की सुविधा, उम्मीद के मुताबिक काम कर रही है या फ़्रीज़र से जुड़ी समस्याओं को हल करने के लिए, गड़बड़ी की जानकारी देने वाले इन टूल और कमांड का इस्तेमाल करें:
ऐक्टिविटी मैनेजर के कमांड
किसी खास प्रोसेस को फ़्रीज़ करने और कंप्रेस करने के लिए, adb shell am कमांड का इस्तेमाल किया जा सकता है:
किसी प्रोसेस को फ़्रीज़ करने के लिए:
adb shell am freeze <process>किसी प्रोसेस को अनफ़्रीज़ करने के लिए:
adb shell am unfreeze <process>किसी प्रोसेस पर पूरी मेमोरी कंप्रेस करने के लिए:
adb shell am compact full <process>
Logcat की जांच करना
किसी प्रोसेस के फ़्रीज़र में माइग्रेट होने या उससे बाहर निकलने पर, फ़्रीज़ और अनफ़्रीज़ की गई एंट्री देखने के लिए, logcat देखें:
adb logcat | grep -i "\(freezing\|froze\)"अनफ़्रीज़ होने की वजह के लॉग, UnfreezeReason प्रोटोकॉल बफ़र enum से, गिने गए मान आउटपुट करते हैं.
Dumpsys की जांच करना
dumpsys activity का इस्तेमाल करके, फ़्रीज़ की गई प्रोसेस की सूची देखें:
adb shell dumpsys activity | grep -A 20 "Apps frozen:"/sys/fs/cgroup/uid_0/cgroup.freeze फ़ाइल की मौजूदगी की जांच करें.
ApplicationExitInfo
पिछली प्रोसेस के बंद होने की वजह जानने के लिए, देखें
ActivityManager.getHistoricalProcessExitReasons.
अगर किसी ऐप्लिकेशन की प्रोसेस, फ़्रीज़र से जुड़ी किसी समस्या की वजह से बंद हुई है, तो बंद होने की वजह
ApplicationExitInfo.REASON_FREEZER पर सेट होती है. उदाहरण के लिए,
फ़्रीज़ होने के दौरान, सिंक्रोनस बाइंडर ट्रांज़ैक्शन मिलने पर.
Perfetto ट्रेसिंग
फ़्रीज़र से जुड़े इवेंट, Perfetto ट्रेस में system_server प्रोसेस के तहत, Freezer नाम के ट्रैक पर एमिट किए जाते हैं:
FreezeऔरUnfreezeस्लाइस से पता चलता है कि किसी प्रोसेस का स्टेटस कब बदला है.updateAppFreezeStateLSPइवेंट से पता चलता है कि सिस्टम सर्वर, फ़्रीज़ करने या अनफ़्रीज़ करने के फ़ैसले लेने के लिए, प्रोसेस के एट्रिब्यूट की दोबारा जांच कब करता है.
Perfetto यूज़र इंटरफ़ेस (यूआई) में, इन इवेंट की सीधे तौर पर जांच की जा सकती है या PerfettoSQL का इस्तेमाल करके इनका विश्लेषण किया जा सकता है:
INCLUDE PERFETTO MODULE slices.with_context;
SELECT *
FROM process_slice
WHERE process_name = "system_server"
AND track_name = "Freezer"
AND (name LIKE "Freeze %" OR name LIKE "Unfreeze %");
PerfettoSQL की स्टैंडर्ड लाइब्रेरी में, फ़्रीज़र इवेंट को android_freezer_events टेबल में भी दिखाया जाता है.