บริการ SystemSuspend

ใน Android 9 และต่ำกว่าจะมีเธรดใน libsuspend ที่รับผิดชอบในการเริ่มการระงับระบบ Android 10 เปิดตัวฟังก์ชันการทำงานที่เทียบเท่าในบริการ HIDL ของ SystemSuspend บริการนี้อยู่ในอิมเมจระบบและแพลตฟอร์ม Android เป็นผู้ให้บริการ ตรรกะจาก libsuspend ยังคงเหมือนเดิมเป็นส่วนใหญ่ ยกเว้นกระบวนการในพื้นที่ผู้ใช้ทุกกระบวนการที่บล็อกการระงับระบบจะต้องสื่อสารกับ SystemSuspend

libsuspend และ libpower

ใน Android 10 บริการ SystemSuspend จะแทนที่ libsuspend libpower ได้รับการติดตั้งใช้งานใหม่เพื่อให้ใช้บริการ SystemSuspend แทน /sys/power/wake[un]lock โดยไม่ต้องเปลี่ยน C API

รหัสเทียมนี้แสดงวิธีใช้ acquire_wake_lock และ release_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 จะติดตามจำนวน Wake Lock ที่ออกโดยใช้ ตัวนับการระงับ โดยมีเธรดการดำเนินการ 2 เธรด ดังนี้

  • เทรดหลักจะตอบการเรียกใช้ Binder
  • เธรด suspend จะควบคุมการระงับระบบ

เทรดหลัก

เธรดหลักจะตอบคำขอจากไคลเอ็นต์เพื่อจัดสรร Wake Lock ใหม่ เพิ่ม/ลดตัวนับการระงับ

ระงับชุดข้อความ

เธรดระงับจะดำเนินการต่อไปนี้ในลูป

  1. อ่านจาก /sys/power/wakeup_count
  2. รับ Mutex ซึ่งช่วยให้มั่นใจว่าเทรดที่ระงับจะไม่แตะต้อง ตัวนับการระงับในขณะที่เทรดหลักพยายาม เพิ่มหรือลดค่า เทรดหลักถูกบล็อก เมื่อออกหรือนำ Wake Lock ออกเมื่อตัวนับการระงับถึง 0 และเทรดระงับพยายามเรียกใช้
  3. รอจนกว่าตัวนับจะเท่ากับ 0
  4. เขียนค่าที่อ่านจาก /sys/power /wakeup_count (จากขั้นตอนที่ 1) ลงในไฟล์นี้ หากการเขียนไม่สำเร็จ ให้กลับไปที่จุดเริ่มต้นของลูป
  5. เริ่มการระงับระบบโดยเขียน mem ไปยัง /sys/power/state
  6. ปล่อย Mutex

เมื่อคำขอ Wake Lock แสดงผลสำเร็จ ระบบจะบล็อกเธรดระงับ

รูปที่ 1 ระงับลูปเธรด

SystemSuspend API

SystemSuspend API ประกอบด้วยอินเทอร์เฟซ 2 รายการ กระบวนการดั้งเดิมใช้ HIDL Interface เพื่อรับ Wake Lock และใช้ AIDL Interface เพื่อ การสื่อสารระหว่าง SystemServer กับ SystemSuspend

อินเทอร์เฟซ HIDL ของ ISystemSuspend


enum WakeLockType : uint32_t {
    PARTIAL,
    FULL
};

interface IWakeLock {
    oneway release();
};

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

ไคลเอ็นต์แต่ละรายที่ขอ Wake Lock จะได้รับอินสแตนซ์ที่ไม่ซ้ำกัน IWakeLock ซึ่งแตกต่างจาก /sys/power/wake_lockที่อนุญาตให้ไคลเอ็นต์หลายราย ใช้ Wake Lock ภายใต้ชื่อเดียวกัน หากไคลเอ็นต์ที่มีอินสแตนซ์ IWakeLock สิ้นสุดลง ไดรเวอร์ Binder และบริการ SystemSuspend จะล้างข้อมูล

อินเทอร์เฟซ AIDL ของ ISuspendControlService

ISuspendControlService มีไว้สำหรับใช้โดย SystemServer เท่านั้น


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

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

การใช้ประโยชน์จาก HIDL ของ Android มีข้อดีดังนี้

  • หากกระบวนการบล็อกการระงับสิ้นสุดลง SystemSuspend จะได้รับการแจ้งเตือน
  • สามารถกำหนดให้เธรดที่รับผิดชอบการระงับระบบมีการเรียกกลับได้