Dịch vụ SystemSuspend

Trong Android 9 trở xuống, có một luồng trong libsuspend chịu trách nhiệm bắt đầu tạm ngưng hệ thống. Android 10 giới thiệu một chức năng tương đương trong dịch vụ SystemSuspend HIDL. Dịch vụ này nằm trong hình ảnh hệ thống và do nền tảng Android phân phát. Logic từ libsuspend vẫn giữ nguyên, ngoại trừ mọi quy trình không gian người dùng chặn trạng thái tạm ngưng hệ thống cần giao tiếp với SystemSuspend.

libsuspend và libpower

Trong Android 10, dịch vụ SystemSuspend sẽ thay thế libsuspend. Triển khai lại libpower để dựa trên dịch vụ SystemSuspend thay vì /sys/power/wake[un]lock mà không cần thay đổi API C.

Mã giả lập này cho biết cách triển khai 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;
}

Luồng thực thi

Dịch vụ SystemSuspend theo dõi số lượng khoá chế độ thức được phát hành bằng một bộ đếm tạm ngưng. Lớp này có hai luồng thực thi:

  • Luồng chính trả lời các lệnh gọi liên kết.
  • Luồng tạm ngưng kiểm soát trạng thái tạm ngưng hệ thống.

Luồng chính

Luồng chính trả lời các yêu cầu của ứng dụng để phân bổ khoá chế độ thức mới, tăng/giảm bộ đếm tạm ngưng.

Tạm ngưng luồng

Luồng tạm ngưng thực hiện những việc sau trong một vòng lặp:

  1. Đọc từ /sys/power/wakeup_count.
  2. Lấy nút mutex. Việc này đảm bảo rằng luồng tạm ngưng không chạm vào bộ đếm tạm ngưng trong khi luồng chính đang cố gắng tăng hoặc giảm nó. Luồng chính bị chặn khi phát hành hoặc xoá khoá chế độ thức khi bộ đếm tạm ngưng đã đạt đến 0 và luồng tạm ngưng đang cố gắng chạy.
  3. Chờ cho đến khi bộ đếm bằng 0.
  4. Ghi giá trị đọc được từ /sys/power /wakeup_count (từ bước 1) vào tệp này. Nếu không ghi được, hãy quay lại đầu vòng lặp
  5. Bắt đầu hệ thống tạm ngưng bằng cách ghi mem vào /sys/power/state.
  6. Huỷ bỏ mutex.

Khi yêu cầu khoá chế độ thức trả về thành công, luồng tạm ngưng sẽ bị chặn.

Hình 1. Vòng lặp luồng tạm ngưng

SystemSuspend API

API SystemSuspend bao gồm hai giao diện. Giao diện HIDL được các quy trình gốc sử dụng để thu nạp khoá chế độ thức, còn giao diện AIDL dùng để giao tiếp giữa SystemServer và SystemSuspend.

Giao diện HIDL ISystemSuspend


enum WakeLockType : uint32_t {
    PARTIAL,
    FULL
};

interface IWakeLock {
    oneway release();
};

interface ISystemSuspend {
    acquireWakeLock(WakeLockType type, string debugName)
        generates (IWakeLock lock);
};

Mỗi ứng dụng yêu cầu khoá chế độ thức sẽ nhận được một thực thể IWakeLock duy nhất. Điều này khác với /sys/power/wake_lock, cho phép nhiều ứng dụng sử dụng khoá chế độ thức theo cùng một tên. Nếu một ứng dụng khách đang giữ một thực thể IWakeLock bị chấm dứt, thì trình điều khiển liên kết và dịch vụ SystemSuspend sẽ dọn dẹp thực thể đó.

Giao diện ISuspendControlService AIDL

ISuspendControlService chỉ dành cho SystemServer sử dụng.


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

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

Việc tận dụng Android HIDL mang lại những lợi ích sau:

  • Nếu một quy trình chặn tạm ngưng bị gián đoạn, SystemSuspend có thể được thông báo.
  • Luồng chịu trách nhiệm tạm ngưng hệ thống có thể được cung cấp lệnh gọi lại.