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 mesaj dizileri

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 kilitleri verirken veya kaldırırken engellenir.
  3. Sayaç sıfıra eşit olana 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. /sys/power/state adresine mem 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ü, yerel işlemler tarafından uyanık kalma kilitleri alınırken, AIDL arayüzü ise SystemServer ile Systemsuspended arasındaki iletişim için kullanılır.

ISystemsuspended 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 izin veren /sys/power/wake_lock ürününden 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ü

IsuspendedControlService 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 yararlanma şu avantajları sağlar:

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