SystemSuspend hizmeti

Android 9 ve önceki sürümlerde, sistemin askıya alınmasını başlatmaktan sorumlu olan libsuspend içinde bir iş parçacığı vardır. 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 sunulur. libsuspend'daki mantık 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 yerine geçer. libpower, C API'sinde değişiklik yapılmadan /sys/power/wake[un]lock yerine SystemSuspend hizmetini kullanacak şekilde yeniden uygulandı.

Bu sözde kodda, acquire_wake_lock ve release_wake_lock öğelerinin 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ıyla verilen uyandırma kilitlerinin sayısını takip eder. İki yürütme iş parçacığı vardır:

  • Bağlayıcı çağrılarını ana ileti dizisi yanıtlar.
  • Askıya alma iş parçacığı, sistemin askıya alınmasını kontrol eder.

Ana iş parçacığı

Ana iş parçacığı, istemcilerin yeni uyandırma kilitleri ayırma, askıya alma sayacını artırma/azaltma isteklerini yanıtlar.

İleti dizisini askıya alma

Askıya alma iş parçacığı, döngü içinde aşağıdakileri yapar:

  1. /sys/power/wakeup_count adlı kullanıcının mesajını okuyun.
  2. Karşılıklı dışlama nesnesini edinir. Bu, askıya alma iş parçacığı, ana iş parçacığı artırmaya veya azaltmaya çalışırken 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ığı, uyandırma kilitleri verilirken veya kaldırılırken engelleniyor.
  3. Sayaç sıfıra ulaşana kadar bekleyin.
  4. /sys/power /wakeup_count'dan (1. adım) 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 yazarak sistem askıya alma işlemini başlatın./sys/power/state
  6. Karşılıklı dışlama kilidini serbest bırakın.

Uyanık kalma 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ü, yerel işlemler tarafından uyandırma kilidi almak için, AIDL arayüzü ise 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);
};

Uyanık tutma kilidi isteyen her istemci, benzersiz bir IWakeLock örneği alır. Bu, /sys/power/wake_lock özelliğinden farklıdır. Bu özellik, birden fazla istemcinin aynı ad altında uyanık tutma kilidini kullanmasına olanak tanır. IWakeLock örneği tutan bir istemci sonlandırılırsa bağlayıcı sürücü ve SystemSuspend hizmeti bunu 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 almayı engelleyen bir işlem sonlanırsa SystemSuspend bilgilendirilebilir.
  • Sistemin askıya alınmasından sorumlu iş parçacığına geri çağırma verilebilir.