SystemSuspend सेवा

Android 9 और उससे पहले वाले वर्शन में, सिस्टम को निलंबित करने की प्रोसेस शुरू करने के लिए libsuspend में एक थ्रेड होती है. Android 10 में, SystemSuspend HIDL सेवा में इसी तरह की सुविधा दी गई है. यह सेवा, सिस्टम इमेज में मौजूद होती है और इसे Android प्लैटफ़ॉर्म से उपलब्ध कराया जाता है. libsuspend का लॉजिक काफ़ी हद तक एक जैसा रहता है. हालांकि, सिस्टम को निलंबित करने से रोकने वाली हर यूज़रस्पेस प्रोसेस को SystemSuspend के साथ कम्यूनिकेट करना होता है.

libsuspend और libpower

Android 10 में, SystemSuspend सेवा libsuspend की जगह लेती है. libpower को फिर से लागू किया गया है, ताकि यह /sys/power/wake[un]lock के बजाय SystemSuspend सेवा पर निर्भर रहे. हालांकि, C API में कोई बदलाव नहीं किया गया है.

इस स्यूडोकोड में, acquire_wake_lock और release_wake_lock को लागू करने का तरीका बताया गया है.


static std::unordered_map<std::string, sp<IWakeLock>> gWakeLockMap;

int acquire_wake_lock(int, const char* id) {
    ...
    if (!gWakeLockMap[id]) {
        gWakeLockMap[id] = suspendService->acquireWakeLock(WakeLockType::PARTIAL, id);
    }
    ...
    return 0;
}

int release_wake_lock(const char* id) {
    ...
    if (gWakeLockMap[id]) {
        auto ret = gWakeLockMap[id]->release();
        gWakeLockMap[id].clear();
        return 0;
    }
    ...
    return -1;
}

एक्ज़ीक्यूशन थ्रेड

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

  • मुख्य थ्रेड, बाइंडर कॉल का जवाब देती है.
  • suspend थ्रेड, सिस्टम को निलंबित करने की सुविधा को कंट्रोल करता है.

मुख्य थ्रेड

मुख्य थ्रेड, क्लाइंट के उन अनुरोधों का जवाब देती है जिनमें नए वेक लॉक असाइन करने के लिए कहा जाता है. साथ ही, यह सस्पेंड काउंटर को बढ़ाती/घटाती है.

थ्रेड को निलंबित करना

सस्पेंड थ्रेड, लूप में ये काम करती है:

  1. /sys/power/wakeup_count से पढ़ें.
  2. म्यूटेक्स हासिल करें. इससे यह पक्का होता है कि निलंबित थ्रेड, निलंबित काउंटर को तब तक नहीं छूती है, जब तक मुख्य थ्रेड उसे बढ़ाने या घटाने की कोशिश कर रही है. जब निलंबन काउंटर शून्य पर पहुंच जाता है और निलंबित थ्रेड चल रही होती है, तब वेक लॉक जारी करने या हटाने पर मुख्य थ्रेड ब्लॉक हो जाती है.
  3. काउंटर के शून्य होने तक इंतज़ार करें.
  4. /sys/power /wakeup_count से पढ़ी गई वैल्यू (पहले चरण से) को इस फ़ाइल में लिखें. अगर लिखने की प्रोसेस पूरी नहीं होती है, तो लूप की शुरुआत पर वापस जाएं
  5. mem को /sys/power/state पर भेजकर, सिस्टम को निलंबित करें.
  6. म्यूटेक्स को रिलीज़ करें.

जब वेक लॉक का अनुरोध पूरा हो जाता है, तो सस्पेंड थ्रेड ब्लॉक हो जाती है.

पहली इमेज. Suspend thread loop

SystemSuspend API

SystemSuspend API में दो इंटरफ़ेस होते हैं. नेटिव प्रोसेस, वेक लॉक पाने के लिए HIDL इंटरफ़ेस का इस्तेमाल करती हैं. वहीं, SystemServer और SystemSuspend के बीच कम्यूनिकेशन के लिए, AIDL इंटरफ़ेस का इस्तेमाल किया जाता है.

ISystemSuspend HIDL इंटरफ़ेस


enum WakeLockType : uint32_t {
    PARTIAL,
    FULL
};

interface IWakeLock {
    oneway release();
};

interface ISystemSuspend {
    acquireWakeLock(WakeLockType type, string debugName)
        generates (IWakeLock lock);
};

वेक लॉक का अनुरोध करने वाले हर क्लाइंट को एक यूनीक IWakeLock इंस्टेंस मिलता है. यह /sys/power/wake_lock से अलग है. इसकी मदद से, एक से ज़्यादा क्लाइंट एक ही नाम से वेक लॉक का इस्तेमाल कर सकते हैं. अगर IWakeLock का इस्तेमाल करने वाला कोई क्लाइंट बंद हो जाता है, तो बाइंडर ड्राइवर और SystemSuspend सेवा इसे हटा देती है.

ISuspendControlService AIDL इंटरफ़ेस

ISuspendControlService का इस्तेमाल सिर्फ़ SystemServer के लिए किया जाता है.


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

interface ISuspendControlService {
    boolean enableAutosuspend();
    boolean registerCallback(ISuspendCallback callback);
    boolean forceSuspend();
}

Android HIDL का इस्तेमाल करने से ये फ़ायदे मिलते हैं:

  • अगर निलंबन को रोकने वाली कोई प्रोसेस बंद हो जाती है, तो SystemSuspend को इसकी सूचना दी जा सकती है.
  • सिस्टम को निलंबित करने के लिए ज़िम्मेदार थ्रेड को कॉलबैक दिया जा सकता है.