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 dừng hệ thống. Android 10 giới thiệu 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à được cung cấp bởi nền tảng Android. Logic từ libsuspend phần lớn vẫn giống nhau, ngoại trừ mọi quy trình không gian người dùng chặn hệ thống tạm dừng cần liên lạc với SystemSuspend.

libsuspend và libpower

Trong Android 10, dịch vụ SystemSuspend 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ả này cho thấy 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;
}

Chủ đề thực thi

Dịch vụ SystemSuspend theo dõi số lượng khóa chế độ thức được cấp bằng bộ đếm tạm dừng. Nó có hai luồng thực thi:

  • Chủ đề chính trả lời các cuộc gọi liên kết.
  • Hệ thống điều khiển luồng đình chỉ tạm dừng.

Chủ đề chính

Chuỗi chính trả lời các yêu cầu từ khách hàng để phân bổ khóa đánh thức mới, tăng/giảm bộ đếm tạm dừng.

Đình chỉ chủ đề

Chuỗi treo thực hiện các hoạt động sau trong một vòng lặp:

  1. Đọc từ /sys/ power /wakeup_count .
  2. Có được mutex. Điều này đảm bảo rằng luồng treo không chạm vào bộ đếm tạm dừ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 xóa khóa đánh thức khi bộ đếm tạm dừng đạt đến 0 và luồng tạm dừng đang cố chạy.
  3. Đợi 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 ghi thất bại, quay lại đầu vòng lặp
  5. Bắt đầu tạm dừ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 khóa chế độ thức được trả về thành công, chuỗi tạm dừng sẽ bị chặn.

Hình 1. Treo vòng chỉ

API tạm dừng hệ thống

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 được khóa đánh thức và giao diện AIDL được sử dụng để liên lạc giữa SystemServer và SystemSuspend.

ISystemSuspend giao diện HIDL


enum WakeLockType : uint32_t {
    PARTIAL,
    FULL
};

interface IWakeLock {
    oneway release();
};

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

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

Giao diện ISuspendControlService AIDL

ISuspendControlService chỉ được sử dụng bởi 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 quá trình chặn tạm dừng bị chết, SystemSuspend có thể được thông báo.
  • Chuỗi chịu trách nhiệm tạm dừng hệ thống có thể được gọi lại.