系統暫停服務

在 Android 9 及更低版本中, libsuspend中有一個執行緒負責啟動系統掛起。 Android 10 在 SystemSuspend HIDL 服務中引進了等效功能。該服務位於系統映像中,由 Android 平台提供服務。除了阻止系統掛起的每個用戶空間程序都需要與 SystemSuspend 通訊之外, libsuspend的邏輯基本上保持不變。

libsuspend 和 libpower

在 Android 10 中, SystemSuspend 服務取代了libsuspendlibpower被重新實現,以依賴 SystemSuspend 服務而不是/sys/ power /wake[un]lock而無需更改 C API。

此偽代碼顯示如何實作acquire_wake_lockrelease_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 服務追蹤使用掛起計數器發出的喚醒鎖定的數量。它有兩個執行線程:

  • 執行緒應答綁定器呼叫。
  • 掛起線程控制系統掛起。

主線

主執行緒回應客戶端的請求來分配新的喚醒鎖,增加/減少掛起計數器。

掛起執行緒

掛起執行緒在迴圈中執行以下操作:

  1. /sys/ power /wakeup_count讀取。
  2. 獲取互斥體。這可以確保當執行緒嘗試增加或減少掛起計數器時,掛起執行緒不會觸及掛起計數器。當掛起計數器達到零並且掛起執行緒嘗試執行時,執行緒在發出或刪除喚醒鎖定時被阻止。
  3. 等到計數器等於零。
  4. 將從/sys/ power /wakeup_count (從步驟 1)讀取的值寫入此檔案。如果寫入失敗,則傳回循環開頭
  5. mem寫入/sys/power/ state啟動系統掛起。
  6. 釋放互斥體。

當喚醒鎖定請求成功返回時,掛起執行緒將被阻塞。

圖 1.掛起線程循環

系統掛起API

SystemSuspend API 由兩個介面組成。 HIDL 介面用於本機程序取得喚醒鎖,AIDL 介面用於 SystemServer 和 SystemSuspend 之間的通訊。

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實例的用戶端終止,binder 驅動程式和 SystemSuspend 服務會將其清除。

ISuspendControlService AIDL 介面

ISuspendControlService 僅供 SystemServer 使用。


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

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

利用 Android HIDL 有以下優點:

  • 如果掛起阻塞程序終止,則可以通知 SystemSuspend。
  • 負責系統掛起的執行緒可以被給予回呼。