บริการระงับระบบ

ใน Android 9 และต่ำกว่า จะมีเธรดใน libsuspend ที่รับผิดชอบในการเริ่มการระงับระบบ Android 10 ได้เปิดตัวฟังก์ชันการทำงานที่เทียบเท่าในบริการ SystemSuspend HIDL บริการนี้อยู่ในภาพระบบและแสดงโดยแพลตฟอร์ม Android ตรรกะจาก libsuspend ยังคงเหมือนเดิมเกือบทั้งหมด ยกเว้นกระบวนการทุกรายการใน Userspace ที่บล็อกการระงับระบบต้องสื่อสารกับ 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 จะติดตามจํานวนการล็อกการปลุกที่ออกมาพร้อมกับตัวนับการระงับ โดยมีการแยกการดําเนินการออกเป็น 2 ด้าย ดังนี้

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

เทรดหลัก

เทรดหลักจะตอบคําขอจากไคลเอ็นต์เพื่อจัดสรรการล็อกการปลุกใหม่ โดยเพิ่ม/ลดตัวนับการระงับ

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

ด้ายที่หยุดชั่วคราวจะดำเนินการต่อไปนี้ในลูป

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

เมื่อคำขอการล็อกการปลุกแสดงผลสำเร็จ ด้ายที่หยุดชั่วคราวจะบล็อก

รูปที่ 1 หยุดการวนซ้ำของชุดข้อความชั่วคราว

SystemSuspend API

SystemSuspend API ประกอบด้วยอินเทอร์เฟซ 2 รายการ อินเทอร์เฟซ HIDL ใช้โดยกระบวนการเนทีฟเพื่อรับการล็อกการปลุก และอินเทอร์เฟซ AIDL ใช้สำหรับการสื่อสารระหว่าง SystemServer กับ SystemSuspend

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


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 สิ้นสุดลง โปรแกรมควบคุม Binder และบริการ SystemSuspend จะล้างข้อมูลดังกล่าว

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

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


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

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

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

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