SystemSuspend hizmeti

Android 9 ve daha düşük sürümlerde, libsuspend'de sistemin askıya alınmasını başlatmaktan sorumlu bir iş parçacığı vardır. Android 10, SystemSuspend HIDL hizmetinde eşdeğer bir işlevsellik sunar. Bu hizmet sistem görüntüsünde bulunur ve Android platformu tarafından sunulur. libsuspend mantığı büyük ölçüde aynı kalır; ancak sistemin askıya alınmasını engelleyen her kullanıcı alanı işleminin SystemSuspend ile iletişim kurması gerekir.

libsuspend ve libpower

Android 10'da SystemSuspend hizmeti libsuspend yerini alıyor. libpower C API'sini değiştirmeden /sys/ power /wake[un]lock yerine SystemSuspend hizmetine güvenecek şekilde yeniden uygulandı.

Bu sözde kod, acquire_wake_lock release_wake_lock nasıl uygulanacağını gösterir.


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;
}

Yürütme konuları

SystemSuspend hizmeti, bir askıya alma sayacıyla birlikte verilen uyanık kalma kilitlerinin sayısını takip eder. İki yürütme iş parçacığı vardır:

  • Ana iş parçacığı ciltleyici çağrılarına yanıt verir.
  • Askıya alma iş parçacığı, sistemin askıya alınmasını kontrol eder.

Ana konu

Ana iş parçacığı, istemcilerden gelen yeni uyandırma kilitleri tahsis etme isteklerini yanıtlayarak, askıya alma sayacını artırır/azaltır.

Konuyu askıya al

Askıya alma iş parçacığı bir döngüde aşağıdakileri gerçekleştirir:

  1. /sys/ power /wakeup_count adresinden okuyun.
  2. Muteksi edinin. Bu, ana iş parçacığı artırmaya veya azaltmaya çalışırken, askıya alma iş parçacığının askıya alma sayacına dokunmamasını sağlar. Askıya alma sayacı sıfıra ulaştığında ve askıya alma iş parçacığı çalışmaya çalışırken ana iş parçacığı uyanık kalma kilitlerinin verilmesi veya kaldırılması sırasında engellenir.
  3. Sayaç sıfıra eşit olana kadar bekleyin.
  4. /sys/ power /wakeup_count (1. adımdan itibaren) okunan değeri bu dosyaya yazın. Yazma başarısız olursa döngünün başına dönün
  5. /sys/power/ state mem yazarak sistemi askıya almayı başlatın.
  6. Muteksi serbest bırakın.

Uyandırma kilidi isteği başarıyla geri döndüğünde, askıya alma iş parçacığı engellenir.

Şekil 1. İplik döngüsünü askıya alma

SystemSuspend API'si

SystemSuspend API iki arayüzden oluşur. HIDL arabirimi, yerel işlemler tarafından uyanık kalma kilitlerini elde etmek için kullanılır ve AIDL arabirimi, SystemServer ile SystemSuspend arasındaki iletişim için kullanılır.

ISystemSuspend HIDL arayüzü


enum WakeLockType : uint32_t {
    PARTIAL,
    FULL
};

interface IWakeLock {
    oneway release();
};

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

Uyandırma kilidi isteyen her istemci benzersiz bir IWakeLock örneği alır. Bu, birden fazla istemcinin aynı ad altında uyanık kalma kilidini kullanmasına olanak tanıyan /sys/ power /wake_lock farklıdır. IWakeLock örneğini tutan bir istemci sonlandırılırsa, bağlayıcı sürücü ve SystemSuspend hizmeti onu temizler.

ISuspendControlService AIDL arayüzü

ISuspendControlService yalnızca SystemServer tarafından kullanılmak üzere tasarlanmıştır.


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

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

Android HIDL'den yararlanmak aşağıdaki avantajları sunar:

  • Askıya alma engelleme işlemi sona ererse SystemSuspend'e bildirim gönderilebilir.
  • Sistemin askıya alınmasından sorumlu iş parçacığına bir geri arama yapılabilir.