SystemSuspend 服務

在 Android 9 以下版本中,libsuspend 有一個負責啟動系統暫停的執行緒。Android 10 在 SystemSuspend HIDL 服務中導入了同等功能。這項服務位於系統映像檔中,由 Android 平台提供。 libsuspend 的邏輯大致相同,但每個會封鎖系統暫停的 userspace 程序,都需要與 SystemSuspend 通訊。

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. 暫停執行緒迴圈

SystemSuspend API

SystemSuspend API 包含兩個介面。原生程序會使用 HIDL 介面取得喚醒鎖定,而 SystemServer 和 SystemSuspend 之間的通訊則使用 AIDL 介面。

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 執行個體的用戶端終止,繫結器驅動程式和 SystemSuspend 服務會清除該執行個體。

ISuspendControlService AIDL 介面

ISuspendControlService 僅供 SystemServer 使用。


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

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

善用 Android HIDL 可帶來下列優點:

  • 如果導致暫停的程序終止,系統可以通知 SystemSuspend。
  • 負責系統暫停的執行緒可以取得回呼。