android STR suspend trigger

android STR suspend trigger

void SystemSuspend::initAutosuspend() {
std::thread autosuspendThread([this] {
while (true) {
std::this_thread::sleep_for(mSleepTime);
lseek(mWakeupCountFd, 0, SEEK_SET);
const string wakeupCount = readFd(mWakeupCountFd);
if (wakeupCount.empty()) {
PLOG(ERROR) << "error reading from /sys/power/wakeup_count";
continue;
}
auto counterLock = std::unique_lock(mCounterLock);
mCounterCondVar.wait(counterLock, [this] { return mSuspendCounter == 0; });
// The mutex is locked and *MUST* remain locked until we write to /sys/power/state.
// Otherwise, a WakeLock might be acquired after we check mSuspendCounter and before we
// write to /sys/power/state.
if (!WriteStringToFd(wakeupCount, mWakeupCountFd)) {
PLOG(VERBOSE) << "error writing from /sys/power/wakeup_count";
continue;
}
bool success = WriteStringToFd(kSleepState, mStateFd);
counterLock.unlock();
if (!success) {
PLOG(VERBOSE) << "error writing to /sys/power/state";
}
mControlService->notifyWakeup(success);
updateSleepTime(success);
}
});
autosuspendThread.detach();
LOG(INFO) << "automatic system suspend enabled";
}

然后WriteStringToFd(wakeupCount, mWakeupCountFd)将上面readFd返回的wakeup cnt写入/sys/power/wakeup_count,这将会call到kernel的pm_save_wakeup_count,如果传下来的count和kernel里的wakeup count相等,并且没有in progress wakeup source,这个函数将返回true;否则返回false。上面readFd(mWakeupCountFd)是一个阻塞调用,如果系统中还有active的wakeup source,这个函数将会阻塞,直到系统中所有的wakeup source都release了,这个函数才会返回,返回截至当前系统中已经完成的wakeup source count。

如果返回true,上面将接着call WriteStringToFd将“mem”写入/sys/power/state执行suspend流程,否则continue调用readFd阻塞调用读取wakeup count系统调用。

bool pm_get_wakeup_count(unsigned int *count, bool block)
{
unsigned int cnt, inpr;

if (block) {
DEFINE_WAIT(wait);

for (;;) {
prepare_to_wait(&wakeup_count_wait_queue, &wait,
TASK_INTERRUPTIBLE); //wait here,挡有wakeup source release时,将wakeup它,即在wakeup_source_deactivate里release一个wakeup source时,将wakeup它
split_counters(&cnt, &inpr);
if (inpr == 0 || signal_pending(current)) //如果系统里没有一个in progress wakeup source,break此死循环,read wakeup count阻塞系统调用将返回
break;
pm_print_active_wakeup_sources();
schedule();
}
finish_wait(&wakeup_count_wait_queue, &wait);
}

split_counters(&cnt, &inpr);
*count = cnt;
return !inpr;
}
bool pm_save_wakeup_count(unsigned int count)
{
unsigned int cnt, inpr;
unsigned long flags;

events_check_enabled = false;
raw_spin_lock_irqsave(&events_lock, flags);
split_counters(&cnt, &inpr);
if (cnt == count && inpr == 0) {
saved_count = count;
events_check_enabled = true;
}
raw_spin_unlock_irqrestore(&events_lock, flags);
return events_check_enabled;
}
原文地址:https://www.cnblogs.com/aspirs/p/15634896.html