आरआईएल रीफ़ैक्टरिंग

Android 7.0 में, RIL की परफ़ॉर्मेंस बेहतर बनाने के लिए, रेडियो इंटरफ़ेस लेयर (RIL) को फिर से डिज़ाइन किया गया है. इसके लिए, कई सुविधाओं का इस्तेमाल किया गया है. इन सुविधाओं को लागू करने के लिए, पार्टनर को कोड में बदलाव करने की ज़रूरत होती है. हालांकि, ये सुविधाएं ज़रूरी नहीं हैं, लेकिन इन्हें लागू करने का सुझाव दिया जाता है. रीफ़ैक्टरिंग में किए गए बदलाव, पुराने सिस्टम के साथ काम करते हैं. इसलिए, रीफ़ैक्टर की गई सुविधाओं के पहले के वर्शन अब भी काम करते हैं.

RIL को फिर से डिज़ाइन करने के बाद, ये सुधार किए गए हैं:

  • RIL से जुड़ी गड़बड़ी के कोड. मौजूदा GENERIC_FAILURE कोड के अलावा, गड़बड़ी के खास कोड भी उपलब्ध हैं. इससे गड़बड़ी की वजह के बारे में ज़्यादा जानकारी मिलती है. इसलिए, गड़बड़ी से जुड़ी समस्या को हल करने में मदद मिलती है.
  • RIL के वर्शन की जानकारी. इससे वर्शन की ज़्यादा सटीक और आसानी से कॉन्फ़िगर की जा सकने वाली जानकारी मिलती है.
  • वेक लॉक का इस्तेमाल करके RIL कम्यूनिकेशन. इससे डिवाइस की बैटरी की परफ़ॉर्मेंस बेहतर होती है.

आपके पास ऊपर बताए गए सभी या किसी भी सुधार को लागू करने का विकल्प होता है. ज़्यादा जानकारी के लिए, RIL के वर्शन की जानकारी से जुड़े कोड के कॉमेंट देखें https://android.googlesource.com/platform/hardware/ril/+/android17-release/include/telephony/ril.h.

RIL से जुड़ी गड़बड़ी के बेहतर कोड लागू करना

RIL के अनुरोध के लिए किए जाने वाले लगभग सभी कॉल, गड़बड़ी होने पर GENERIC_FAILURE गड़बड़ी कोड दिखा सकते हैं. ओईएम से मिले सभी अनुरोधित जवाबों में यह समस्या होती है. अगर अलग-अलग वजहों से RIL कॉल, GENERIC_FAILURE गड़बड़ी कोड दिखाता है, तो गड़बड़ी की रिपोर्ट से किसी समस्या को डीबग करना मुश्किल हो सकता है. वेंडर को यह पता लगाने में भी काफ़ी समय लग सकता है कि कोड के किस हिस्से से GENERIC_FAILURE कोड मिला है.

Android 7.x और इसके बाद के वर्शन में, ओईएम, गड़बड़ी के हर कोड के लिए अलग-अलग वैल्यू दिखा सकते हैं. फ़िलहाल, इन सभी को GENERIC_FAILURE के तौर पर कैटगरी में रखा गया है. जिन ओईएम को गड़बड़ी के अपने कस्टम कोड सार्वजनिक तौर पर नहीं दिखाने हैं वे गड़बड़ियों को इंटिजर के अलग-अलग सेट (जैसे, 1 से x) के तौर पर दिखा सकते हैं. इन्हें OEM_ERROR_1 से OEM_ERROR_X के तौर पर मैप किया जाता है. वेंडर को यह पक्का करना चाहिए कि गड़बड़ी के हर ऐसे कोड को कोड में गड़बड़ी की किसी खास वजह से मैप किया गया हो. गड़बड़ी के खास कोड का इस्तेमाल करने से, RIL को डीबग करने की प्रोसेस तेज़ हो सकती है. ऐसा तब होता है, जब ओईएम से सामान्य गड़बड़ियां मिलती हैं. ऐसा इसलिए, क्योंकि GENERIC_FAILURE गड़बड़ी कोड की सटीक वजह की पहचान करने में अक्सर बहुत ज़्यादा समय लग सकता है. कई बार, इसकी वजह का पता लगाना मुमकिन नहीं होता.

इसके अलावा, ril.h में RIL_LastCallFailCause और RIL_DataCallFailCause enum के लिए, गड़बड़ी के ज़्यादा कोड जोड़े गए हैं. इससे वेंडर कोड, CALL_FAIL_ERROR_UNSPECIFIED और PDP_FAIL_ERROR_UNSPECIFIED जैसी सामान्य गड़बड़ियां दिखाने से बच सकता है.

RIL से जुड़ी गड़बड़ी के बेहतर कोड की पुष्टि करना

GENERIC_FAILURE कोड की जगह गड़बड़ी के नए कोड जोड़ने के बाद, पुष्टि करें कि RIL कॉल से GENERIC_FAILURE के बजाय, गड़बड़ी के नए कोड मिल रहे हैं.

RIL के वर्शन की बेहतर जानकारी लागू करना

Android के पुराने वर्शन में, RIL के वर्शन की जानकारी से जुड़ी समस्या थी: वर्शन की जानकारी सटीक नहीं थी, RIL के वर्शन की जानकारी देने का तरीका साफ़ नहीं था. इस वजह से, कुछ वेंडर गलत वर्शन की जानकारी देते थे. साथ ही, वर्शन का अनुमान लगाने का तरीका सटीक नहीं था.

Android 7.x और इसके बाद के वर्शन में, ril.h में RIL के सभी वर्शन की वैल्यू की जानकारी दी गई है. इसमें RIL के वर्शन की जानकारी और उस वर्शन के लिए किए गए सभी बदलावों की सूची शामिल है. RIL के किसी वर्शन के मुताबिक बदलाव करने पर, वेंडर को कोड में अपना वर्शन अपडेट करना होगा. साथ ही, RIL_REGISTER में वह वर्शन दिखाना होगा.

RIL के वर्शन की बेहतर जानकारी की पुष्टि करना

पुष्टि करें कि RIL_REGISTER के दौरान, आपके RIL कोड के मुताबिक RIL का वर्शन दिखाया जा रहा है. न कि ril.h में तय किया गया RIL_VERSION.

वेक लॉक का इस्तेमाल करके RIL कम्यूनिकेशन लागू करना

RIL कम्यूनिकेशन में, टाइमर वाले वेक लॉक का इस्तेमाल सटीक तरीके से नहीं किया जाता. इससे बैटरी की परफ़ॉर्मेंस पर बुरा असर पड़ता है. Android 7.x और इसके बाद के वर्शन में, RIL के अनुरोधों को कैटगरी में बांटकर और अलग-अलग तरह के अनुरोधों के लिए, वेक लॉक को अलग-अलग तरीके से मैनेज करने के लिए कोड अपडेट करके, परफ़ॉर्मेंस को बेहतर बनाया जा सकता है.

RIL के अनुरोधों को कैटगरी में बांटना

RIL के अनुरोध, अनुरोधित या बिना अनुरोधित हो सकते हैं. वेंडर को अनुरोधित अनुरोधों को इनमें से किसी एक कैटगरी में बांटना चाहिए:

  • सिंक्रोनस. ऐसे अनुरोध जिनका जवाब देने में ज़्यादा समय नहीं लगता. उदाहरण के लिए, RIL_REQUEST_GET_SIM_STATUS.
  • एसिंक्रोनस. ऐसे अनुरोध जिनका जवाब देने में ज़्यादा समय लगता है. उदाहरण के लिए, RIL_REQUEST_QUERY_AVAILABLE_NETWORKS.

अनुरोधित एसिंक्रोनस RIL अनुरोधों में ज़्यादा समय लग सकता है. वेंडर कोड से ack मिलने के बाद, RIL Java, वेक लॉक को रिलीज़ कर देता है. इससे ऐप्लिकेशन प्रोसेसर, आइडल से सस्पेंड स्टेट में जा सकता है. जब वेंडर कोड से जवाब मिलता है, तो RIL Java (ऐप्लिकेशन प्रोसेसर) वेक लॉक को फिर से हासिल कर लेता है, जवाब को प्रोसेस करता है, और फिर आइडल स्टेट में वापस आ जाता है. आइडल से सस्पेंड और फिर आइडल स्टेट में जाने से, ज़्यादा पावर खर्च हो सकती है.

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

RIL कम्यूनिकेशन के उदाहरण

यहां दिए गए डायग्राम में, RIL कम्यूनिकेशन के सामान्य उदाहरण दिए गए हैं. साथ ही, RIL के अनुरोधित और बिना अनुरोधित अनुरोधों को मैनेज करने के लिए, कोड में बदलाव करने के तरीके बताए गए हैं.

ध्यान दें: यहां दिए गए डायग्राम में इस्तेमाल किए गए फ़ंक्शन के बारे में ज़्यादा जानकारी पाने के लिए, ril.cpp में acquireWakeLock(), decrementWakeLock(), और clearWakeLock() तरीके देखें.

उदाहरण: RIL का अनुरोध और अनुरोधित एसिंक्रोनस रिस्पॉन्स

इस उदाहरण में, अगर RIL के अनुरोधित रिस्पॉन्स में ज़्यादा समय लगने की उम्मीद है (यानी, RIL_REQUEST_GET_AVAILABLE_NETWORKS के जवाब में), तो ऐप्लिकेशन प्रोसेसर की ओर से वेक लॉक को ज़्यादा समय तक होल्ड किया जाता है. मॉडेम की समस्याओं की वजह से भी, ज़्यादा समय लग सकता है.

पहली इमेज. RIL का अनुरोधित एसिंक्रोनस रिस्पॉन्स.

पहला तरीका: मॉडेम, RIL के अनुरोध और एसिंक्रोनस रिस्पॉन्स के लिए वेक लॉक को होल्ड करता है.

दूसरी इमेज. मॉडेम ने वेक लॉक को होल्ड किया है.
  1. RIL का अनुरोध भेजा जाता है और मॉडेम, उस अनुरोध को प्रोसेस करने के लिए वेक लॉक हासिल करता है.
  2. मॉडेम, ack भेजता है. इससे Java की ओर से वेक लॉक काउंटर की वैल्यू कम हो जाती है और काउंटर की वैल्यू 0 होने पर, वेक लॉक रिलीज़ हो जाता है.

    ध्यान दें: अनुरोध-ack सीक्वेंस के लिए, वेक लॉक का टाइम आउट होने की अवधि, फ़िलहाल इस्तेमाल की जा रही टाइम आउट अवधि से कम होगी. ऐसा इसलिए, क्योंकि ack, बहुत तेज़ी से मिल जाना चाहिए.

  3. अनुरोध को प्रोसेस करने के बाद, मॉडेम, वेंडर कोड को इंटरप्ट भेजता है. इससे वेंडर कोड, वेक लॉक हासिल करता है और ril.cpp को रिस्पॉन्स भेजता है. इसके बाद, ril.cpp, वेक लॉक हासिल करता है और Java की ओर से रिस्पॉन्स भेजता है.
  4. जब रिस्पॉन्स, Java की ओर से मिलता है, तो वेक लॉक हासिल किया जाता है और कॉल करने वाले (कॉलर) को रिस्पॉन्स भेजा जाता है.
  5. सभी मॉड्यूल से रिस्पॉन्स प्रोसेस होने के बाद, ril.cpp को (सॉकेट के ज़रिए) ack भेजा जाता है. इसके बाद, ril.cpp, तीसरे चरण में हासिल किए गए वेक लॉक को रिलीज़ कर देता है.

दूसरा तरीका: मॉडेम, वेक लॉक को होल्ड नहीं करता और रिस्पॉन्स तेज़ी से मिलता है (सिंक्रोनस RIL अनुरोध और रिस्पॉन्स). सिंक्रोनस और एसिंक्रोनस व्यवहार को RIL के किसी खास कमांड के लिए हार्डकोड किया जाता है. साथ ही, इसे कॉल-बाय-कॉल के आधार पर तय किया जाता है.

तीसरी इमेज. मॉडेम ने वेक लॉक को होल्ड नहीं किया है.
  1. Java की ओर से acquireWakeLock() को कॉल करके, RIL का अनुरोध भेजा जाता है.
  2. वेंडर कोड को वेक लॉक हासिल करने की ज़रूरत नहीं होती. वह अनुरोध को प्रोसेस कर सकता है और तेज़ी से जवाब दे सकता है.
  3. जब Java की ओर से रिस्पॉन्स मिलता है, तो decrementWakeLock() को कॉल किया जाता है. इससे वेक लॉक काउंटर की वैल्यू कम हो जाती है और काउंटर की वैल्यू 0 होने पर, वेक लॉक रिलीज़ हो जाता है.

उदाहरण: RIL का बिना अनुरोधित रिस्पॉन्स

इस उदाहरण में, RIL के बिना अनुरोधित रिस्पॉन्स में, एक वेक लॉक टाइप फ़्लैग होता है. इससे पता चलता है कि वेंडर के रिस्पॉन्स के लिए वेक लॉक हासिल करना है या नहीं. अगर फ़्लैग सेट है, तो टाइमर वाला वेक लॉक सेट किया जाता है और रिस्पॉन्स को सॉकेट के ज़रिए Java की ओर से भेजा जाता है. टाइमर खत्म होने पर, वेक लॉक रिलीज़ हो जाता है. RIL के बिना अनुरोधित अलग-अलग रिस्पॉन्स के लिए, टाइमर वाला वेक लॉक बहुत ज़्यादा या बहुत कम हो सकता है.

चौथी इमेज. RIL का अनचाहा रिस्पॉन्स.

तरीका: बिना अनुरोधित रिस्पॉन्स भेजते समय, नेटिव साइड (ril.cpp) पर टाइमर वाला वेक लॉक होल्ड करने के बजाय, Java कोड से नेटिव साइड पर एक ack भेजा जाता है.

पांचवी इमेज. टाइमर वाले वेक लॉक के बजाय, ack का इस्तेमाल करना.

फिर से डिज़ाइन किए गए वेक लॉक की पुष्टि करना

पुष्टि करें कि RIL कॉल को सिंक्रोनस या एसिंक्रोनस के तौर पर पहचाना गया है. बैटरी की पावर की खपत, हार्डवेयर/प्लैटफ़ॉर्म पर निर्भर कर सकती है. इसलिए, वेंडर को इंटरनल टेस्टिंग करनी चाहिए. इससे यह पता चलेगा कि एसिंक्रोनस कॉल के लिए, वेक लॉक के नए सिमैंटिक का इस्तेमाल करने से बैटरी की पावर सेव होती है या नहीं.