From: Tri Vo Date: Thu, 20 Sep 2018 23:07:23 +0000 (-0700) Subject: Implement exponential backoff analogous to libsuspend X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=5d524a1d61;p=android-x86%2Fsystem-hardware-interfaces.git Implement exponential backoff analogous to libsuspend Suspends attempts are not free w.r.t. power consumption. This change prevents rapid battery drain on devices with broken system suspend (e.g. due to faulty driver) Originally implemented in libususpend in commit fb896944b6a78d951c8442b444af860a28117e5c Bug: 78888165 Test: SystemSuspendV1_0UnitTest Test: left device overnight, ~50% fewer failed attempts to suspend with this change vs without. Change-Id: Icff1135b9c316fa9de1558ecea42db9ed0d10d9a --- diff --git a/suspend/1.0/default/SystemSuspend.cpp b/suspend/1.0/default/SystemSuspend.cpp index bffc0e3..5f70671 100644 --- a/suspend/1.0/default/SystemSuspend.cpp +++ b/suspend/1.0/default/SystemSuspend.cpp @@ -77,8 +77,13 @@ void WakeLock::releaseOnce() { }); } -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 SystemSuspend::enableAutosuspend() { static bool initialized = false; @@ -165,6 +170,7 @@ void SystemSuspend::deleteWakeLockStatsEntry(WakeLockIdType id) { 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()) { @@ -192,12 +198,23 @@ void SystemSuspend::initAutosuspend() { 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 diff --git a/suspend/1.0/default/SystemSuspend.h b/suspend/1.0/default/SystemSuspend.h index ac799e9..1e83b2c 100644 --- a/suspend/1.0/default/SystemSuspend.h +++ b/suspend/1.0/default/SystemSuspend.h @@ -42,6 +42,8 @@ using ::android::hardware::Return; using WakeLockIdType = uint64_t; +using namespace std::chrono_literals; + class SystemSuspend; std::string readFd(int fd); @@ -62,7 +64,8 @@ class WakeLock : public IWakeLock { 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 enableAutosuspend() override; Return> acquireWakeLock(WakeLockType type, const hidl_string& name) override; Return registerCallback(const sp& cb) override; @@ -94,6 +97,12 @@ class SystemSuspend : public ISystemSuspend, public hidl_death_recipient { 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 diff --git a/suspend/1.0/default/SystemSuspendUnitTest.cpp b/suspend/1.0/default/SystemSuspendUnitTest.cpp index 3f46a3e..968e52f 100644 --- a/suspend/1.0/default/SystemSuspendUnitTest.cpp +++ b/suspend/1.0/default/SystemSuspendUnitTest.cpp @@ -50,6 +50,7 @@ using android::system::suspend::V1_0::IWakeLock; 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 { @@ -79,8 +80,8 @@ class SystemSuspendTestEnvironment : public ::testing::Environment { void registerTestService() { std::thread testService([this] { configureRpcThreadpool(1, true /* callerWillJoin */); - sp suspend = - new SystemSuspend(std::move(wakeupCountFds[1]), std::move(stateFds[1])); + sp 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; diff --git a/suspend/1.0/default/main.cpp b/suspend/1.0/default/main.cpp index 24f0af4..2dce6fd 100644 --- a/suspend/1.0/default/main.cpp +++ b/suspend/1.0/default/main.cpp @@ -17,6 +17,7 @@ using android::hardware::configureRpcThreadpool; 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"; @@ -34,7 +35,8 @@ int main() { } configureRpcThreadpool(1, true /* callerWillJoin */); - sp suspend = new SystemSuspend(std::move(wakeupCountFd), std::move(stateFd)); + sp 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;