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

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

libsuspend และ libpower

ใน Android 10 บริการ Systemsuspended จะมาแทนที่ 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
  • ชุดข้อความที่ถูกระงับจะควบคุมการระงับของระบบ

เทรดหลัก

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

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

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

  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

อินเทอร์เฟซ ISystemsuspended HIDL


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 และบริการ Systemการระงับบัญชี จะล้างข้อมูลดังกล่าว

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

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


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

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

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

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