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. libpower được triển khai lại để dựa vào dịch vụ SystemSuspend thay vì /sys/power/wake[un]lock mà không 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. Thu nạp mutex. Điều 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 bộ đếm đó. 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 tạm ngưng hệ thống bằng cách ghi mem vào /sys/power/state.
  6. Giải phóng 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. Tạm ngưng vòng lặp luồ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 để lấy khoá chế độ thức và giao diện AIDL được 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 dưới 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 AIDL ISuspendControlService

ISuspendControlService chỉ dành cho SystemServer.


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.