SystemAskıya Alma hizmeti

Android 9 ve önceki sürümlerde, sistemin askıya alınmasını başlatmaktan sorumlu bir mesaj dizisi libsuspend içinde bulunur. Android 10, SystemSuspend HIDL hizmetinde eşdeğer bir işlev sunar. Bu hizmet, sistem görüntüsünde bulunur ve Android platformu tarafından yayınlanır. libsuspend'teki mantık büyük ölçüde aynı kalır. Bununla birlikte, sistem askıya alma işlemini engelleyen her kullanıcı alanı işleminin SystemSuspend ile iletişim kurması gerekir.

libsuspend ve libpower

Android 10'da SystemSuspend hizmeti, libsuspend hizmetinin yerini alır. libpower, C API'si değiştirilmeden /sys/power/wake[un]lock yerine SystemSuspend hizmetini kullanacak şekilde yeniden uygulandı.

Bu sözde kodda, acquire_wake_lock ve release_wake_lock işlevlerinin nasıl uygulanacağı gösterilmektedir.


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 iş parçacıkları

SystemSuspend hizmeti, askıya alma sayacı ile verilen uyanma kilitlerinin sayısını izler. İki yürütme iş parçacığı vardır:

  • Ana ileti dizisi, bağlayıcı çağrılarını yanıtlar.
  • suspend mesaj dizisi, sistemin askıya alınmasını kontrol eder.

Ana iş parçacığı

Ana mesaj dizisi, istemcilerden gelen yeni uyanma kilidi ayırma isteklerini yanıtlayarak askıya alma sayacını artırır/azaltır.

Mesaj dizisini askıya alma

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

  1. /sys/power/wakeup_count'ten okuyun.
  2. Müşteriye özel kilidi alın. Bu sayede, ana iş parçacığı askıya alma sayacını artırmaya veya azaltmaya çalışırken askıya alma iş parçacığı bu sayaca dokunmaz. 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ığı, uyanma kilitlerini verme veya kaldırma işleminde engellenir.
  3. Sayaç sıfıra eşitlenene kadar bekleyin.
  4. /sys/power /wakeup_count (1. adımdan) okunan değeri bu dosyaya yazın. Yazma işlemi başarısız olursa döngünün başına dönün
  5. mem /sys/power/state yazarak sistemi askıya alma işlemini başlatın.
  6. Müşteriye özel kilidi bırakın.

Bir uyanma kilidi isteği başarıyla döndürüldüğünde askıya alma iş parçacığı engellenir.

Şekil 1. İş parçacığı döngüsünü askıya alma

SystemSuspend API

SystemSuspend API iki arayüzden oluşur. HIDL arayüzü, uyanma kilitlerini edinmek için yerel işlemler tarafından kullanılır ve AIDL arayüzü, 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 uyanma kilidini kullanmasına olanak tanıyan /sys/power/wake_lock'ten farklıdır. IWakeLock örneğini tutan bir istemci sonlandırılırsa bağlayıcı sürücüsü ve SystemSuspend hizmeti bu örneği 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 yararlanmanın avantajları şunlardır:

  • Askıya alma işlemini engelleyen bir işlem sona ererse SystemSuspend bilgilendirilebilir.
  • Sistem askıya alma işleminden sorumlu olan ileti dizisine geri çağırma çağrısı verilebilir.