OSDN Git Service

Implement exponential backoff analogous to libsuspend
authorTri Vo <trong@google.com>
Thu, 20 Sep 2018 23:07:23 +0000 (16:07 -0700)
committerTri Vo <trong@google.com>
Wed, 26 Sep 2018 23:16:16 +0000 (16:16 -0700)
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

suspend/1.0/default/SystemSuspend.cpp
suspend/1.0/default/SystemSuspend.h
suspend/1.0/default/SystemSuspendUnitTest.cpp
suspend/1.0/default/main.cpp

index bffc0e3..5f70671 100644 (file)
@@ -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<bool> 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
index ac799e9..1e83b2c 100644 (file)
@@ -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<bool> enableAutosuspend() override;
     Return<sp<IWakeLock>> acquireWakeLock(WakeLockType type, const hidl_string& name) override;
     Return<bool> registerCallback(const sp<ISystemSuspendCallback>& 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
index 3f46a3e..968e52f 100644 (file)
@@ -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<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;
index 24f0af4..2dce6fd 100644 (file)
@@ -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<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;