});
}
-SystemSuspend::SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd)
- : mSuspendCounter(0), mWakeupCountFd(std::move(wakeupCountFd)), mStateFd(std::move(stateFd)) {}
+SystemSuspend::SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd,
+ std::chrono::milliseconds baseSleepTime)
+ : mSuspendCounter(0),
+ mWakeupCountFd(std::move(wakeupCountFd)),
+ mStateFd(std::move(stateFd)),
+ mBaseSleepTime(baseSleepTime),
+ mSleepTime(baseSleepTime) {}
Return<bool> SystemSuspend::enableAutosuspend() {
static bool initialized = false;
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()) {
for (const auto& callback : mCallbacks) {
callback->notifyWakeup(success).isOk(); // ignore errors
}
+ updateSleepTime(success);
}
});
autosuspendThread.detach();
LOG(INFO) << "automatic system suspend enabled";
}
+void SystemSuspend::updateSleepTime(bool success) {
+ static constexpr std::chrono::milliseconds kMaxSleepTime = 1min;
+ if (success) {
+ mSleepTime = mBaseSleepTime;
+ return;
+ }
+ // Double sleep time after each failure up to one minute.
+ mSleepTime = std::min(mSleepTime * 2, kMaxSleepTime);
+}
+
} // namespace V1_0
} // namespace suspend
} // namespace system
using WakeLockIdType = uint64_t;
+using namespace std::chrono_literals;
+
class SystemSuspend;
std::string readFd(int fd);
class SystemSuspend : public ISystemSuspend, public hidl_death_recipient {
public:
- SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd);
+ SystemSuspend(unique_fd wakeupCountFd, unique_fd stateFd,
+ std::chrono::milliseconds baseSleepTime);
Return<bool> enableAutosuspend() override;
Return<sp<IWakeLock>> acquireWakeLock(WakeLockType type, const hidl_string& name) override;
Return<bool> registerCallback(const sp<ISystemSuspendCallback>& cb) override;
return std::find_if(mCallbacks.begin(), mCallbacks.end(),
[&cb](const CbType& i) { return interfacesEqual(i, cb); });
}
+
+ // Amount of sleep time between consecutive iterations of the suspend loop.
+ std::chrono::milliseconds mBaseSleepTime;
+ std::chrono::milliseconds mSleepTime;
+ // Updates sleep time depending on the result of suspend attempt.
+ void updateSleepTime(bool success);
};
} // namespace V1_0
using android::system::suspend::V1_0::readFd;
using android::system::suspend::V1_0::SystemSuspend;
using android::system::suspend::V1_0::WakeLockType;
+using namespace std::chrono_literals;
namespace android {
void registerTestService() {
std::thread testService([this] {
configureRpcThreadpool(1, true /* callerWillJoin */);
- sp<ISystemSuspend> suspend =
- new SystemSuspend(std::move(wakeupCountFds[1]), std::move(stateFds[1]));
+ sp<ISystemSuspend> suspend = new SystemSuspend(
+ std::move(wakeupCountFds[1]), std::move(stateFds[1]), 0ms /* baseSleepTime */);
status_t status = suspend->registerAsService(kServiceName);
if (android::OK != status) {
LOG(FATAL) << "Unable to register service: " << status;
using android::hardware::joinRpcThreadpool;
using android::system::suspend::V1_0::ISystemSuspend;
using android::system::suspend::V1_0::SystemSuspend;
+using namespace std::chrono_literals;
static constexpr char kSysPowerWakeupCount[] = "/sys/power/wakeup_count";
static constexpr char kSysPowerState[] = "/sys/power/state";
}
configureRpcThreadpool(1, true /* callerWillJoin */);
- sp<ISystemSuspend> suspend = new SystemSuspend(std::move(wakeupCountFd), std::move(stateFd));
+ sp<ISystemSuspend> suspend =
+ new SystemSuspend(std::move(wakeupCountFd), std::move(stateFd), 100ms /* baseSleepTime */);
status_t status = suspend->registerAsService();
if (android::OK != status) {
LOG(FATAL) << "Unable to register service: " << status;