سرویس SystemSuspend

در اندروید 9 و پایین‌تر یک رشته در libsuspend وجود دارد که مسئول شروع تعلیق سیستم است. اندروید 10 یک عملکرد معادل را در یک سرویس SystemSuspend HIDL معرفی می کند. این سرویس در تصویر سیستم قرار دارد و توسط پلتفرم اندروید ارائه می شود. منطق libsuspend تا حد زیادی یکسان است، به جز هر فرآیند فضای کاربر که تعلیق سیستم را مسدود می کند، نیاز به ارتباط با SystemSuspend دارد.

libsuspend و libpower

در اندروید 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های صادر شده با شمارنده تعلیق را پیگیری می کند. دارای دو رشته اجرایی است:

  • موضوع اصلی به تماس های کلاسور پاسخ می دهد.
  • thread تعلیق سیستم تعلیق را کنترل می کند.

موضوع اصلی

موضوع اصلی به درخواست‌های مشتریان برای تخصیص وایک‌لاک‌های جدید، افزایش/کاهش شمارنده تعلیق پاسخ می‌دهد.

نخ را معلق کنید

thread suspend موارد زیر را در یک حلقه انجام می دهد:

  1. خواندن از /sys/ power /wakeup_count .
  2. mutex را بدست آورید. این باعث می‌شود که در حالی که نخ اصلی سعی می‌کند آن را کم یا زیاد کند، نخ تعلیق با شمارنده تعلیق تماس نگیرد. هنگامی که شمارنده تعلیق به صفر رسیده است و رشته تعلیق در تلاش است تا اجرا شود، نخ اصلی در هنگام صدور یا حذف wake lock مسدود می شود.
  3. صبر کنید تا شمارنده برابر با صفر شود.
  4. مقدار خوانده شده از /sys/ power /wakeup_count (از مرحله 1) را در این فایل بنویسید. اگر نوشتن ناموفق بود، به ابتدای حلقه برگردید
  5. با نوشتن mem در /sys/power/ state سیستم تعلیق را شروع کنید.
  6. موتکس را آزاد کنید.

هنگامی که یک درخواست برای wake lock با موفقیت باز می گردد، رشته تعلیق مسدود می شود.

شکل 1. حلقه نخ را معلق کنید

SystemSuspend API

SystemSuspend API از دو رابط تشکیل شده است. رابط HIDL توسط فرآیندهای بومی برای بدست آوردن wake lock و رابط 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);
};

هر کلاینتی که درخواست wake lock می کند یک نمونه IWakeLock منحصر به فرد دریافت می کند. این با /sys/ power /wake_lock متفاوت است، که به چندین کلاینت اجازه می‌دهد از wake lock تحت یک نام استفاده کنند. اگر سرویس گیرنده ای که نمونه IWakeLock را در اختیار دارد خاتمه یابد، درایور بایندر و سرویس SystemSuspend آن را پاک می کنند.

رابط AIDL ISuspendControlService

ISuspendControlService در نظر گرفته شده است که فقط توسط SystemServer استفاده شود.


interface ISuspendCallback {
     void notifyWakeup(boolean success);
}

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

استفاده از Android HIDL مزایای زیر را ارائه می دهد:

  • اگر یک فرآیند مسدود کردن تعلیق از بین برود، SystemSuspend می تواند مطلع شود.
  • می توان به رشته ای که مسئول تعلیق سیستم است، یک تماس پاسخ داد.