در Android 9 و نسخههای پایینتر، رشتهای در libsuspend
مسئول شروع تعلیق سیستم است. Android 10
عملکردی معادل را در سرویس SystemSuspend HIDL معرفی میکند.
این سرویس در تصویر سیستم قرار دارد و توسط پلاتفرم Android ارائه میشود.
منطق libsuspend تا حد زیادی یکسان است، با این تفاوت که هر فرایند فضای کاربر که تعلیق سیستم را مسدود میکند باید با SystemSuspend ارتباط برقرار کند.
libsuspend و libpower
در Android 10، سرویس SystemSuspend جایگزین
libsuspend میشود. libpower دوباره پیادهسازی شد تا بهجای
/sys/power/wake[un]lock
به سرویس SystemSuspend متکی باشد
بدون اینکه «میانای برنامهسازی کاربردی C» تغییر کند.
این شبهکد نحوه پیادهسازی 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 تعداد قفلهای بیداری صادرشده را با شمارنده تعلیق پیگیری میکند. دو رشته اجرا دارد:
- رشته اصلی به فراخوانیهای binder پاسخ میدهد.
- رشته تعلیق کنترل تعلیق سیستم را انجام میدهد.
رشته اصلی
رشته اصلی به درخواستهای مشتریان برای تخصیص قفلهای بیداری جدید پاسخ میدهد و شمارنده تعلیق را افزایش/کاهش میدهد.
تعلیق کردن رشته
رشته تعلیق در یک حلقه، موارد زیر را انجام میدهد:
- از
/sys/power/wakeup_countبخوان. - موتکس را بهدست آورید. این کار تضمین میکند که رشته تعلیق درحالیکه رشته اصلی درحال تلاش برای افزایش یا کاهش شمارنده تعلیق است، شمارنده تعلیق را لمس نکند. رشته اصلی هنگام صدور یا برداشتن قفلهای بیدارباش وقتی شمارنده تعلیق به صفر رسیده است و رشته تعلیق درحال تلاش برای اجرا است، مسدود میشود.
- صبر کنید تا شمارنده به صفر برسد.
- مقدار خواندهشده از
/sys/power /wakeup_count(از مرحله ۱) را در این فایل بنویسید. اگر نوشتن ناموفق بود، به ابتدای حلقه برگردید - تعلیق سیستم را با نوشتن
memدر/sys/power/stateشروع کنید. - mutex را رها کنید.
وقتی درخواست قفل بیداری باموفقیت برمیگردد، رشته تعلیق مسدود میشود.
SystemSuspend API
SystemSuspend API از دو میانواره تشکیل شده است. از میانای HIDL برای فرایندهای بومی برای دریافت قفلهای بیداری استفاده میشود و از میانای AIDL برای ارتباط بین SystemServer و SystemSuspend استفاده میشود.
میانای ISystemSuspend 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 و
سرویس SystemSuspend آن را پاکسازی میکند.
میانای ISuspendControlService AIDL
ISuspendControlService فقط برای استفاده توسط SystemServer درنظر گرفته شده است.
interface ISuspendCallback {
void notifyWakeup(boolean success);
}
interface ISuspendControlService {
boolean enableAutosuspend();
boolean registerCallback(ISuspendCallback callback);
boolean forceSuspend();
}
استفاده از Android HIDL مزایای زیر را ارائه میدهد:
- اگر فرایند مسدود کردن تعلیق ازکار بیفتد، میتوان به SystemSuspend اطلاع داد.
- رشته مسئول تعلیق سیستم میتواند یک پاسخ تماس دریافت کند.