summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTim Murray2016-10-11 16:18:27 -0500
committerTim Murray2016-10-11 16:51:34 -0500
commitfb896944b6a78d951c8442b444af860a28117e5c (patch)
treedcb9ee136bed1e1fdfd0800cdbb9a50550cf6206 /libsuspend
parent5639d9ad6ef0157586bfb5df35056039b611a448 (diff)
downloadplatform-system-core-fb896944b6a78d951c8442b444af860a28117e5c.tar.gz
platform-system-core-fb896944b6a78d951c8442b444af860a28117e5c.tar.xz
platform-system-core-fb896944b6a78d951c8442b444af860a28117e5c.zip
libsuspend: move to exponential backoff
If for some reason the system can't suspend (usually a driver bug), libsuspend will currently attempt to retry suspend after 100ms. Because entering suspend takes a significant amount of CPU time, this can be extremely expensive and be a major contributor to rapid battery drain. Move autosuspend to use exponential backoff if the previous suspend attempt failed. bug 32092914 Change-Id: I3e9e944f290de5f1853a02e3f61721ba9159df46
Diffstat (limited to 'libsuspend')
-rw-r--r--libsuspend/autosuspend_wakeup_count.c24
1 files changed, 19 insertions, 5 deletions
diff --git a/libsuspend/autosuspend_wakeup_count.c b/libsuspend/autosuspend_wakeup_count.c
index 23a029027..de345492b 100644
--- a/libsuspend/autosuspend_wakeup_count.c
+++ b/libsuspend/autosuspend_wakeup_count.c
@@ -21,6 +21,7 @@
21#include <stddef.h> 21#include <stddef.h>
22#include <stdbool.h> 22#include <stdbool.h>
23#include <string.h> 23#include <string.h>
24#include <sys/param.h>
24#include <sys/stat.h> 25#include <sys/stat.h>
25#include <sys/types.h> 26#include <sys/types.h>
26#include <unistd.h> 27#include <unistd.h>
@@ -34,12 +35,24 @@
34#define SYS_POWER_STATE "/sys/power/state" 35#define SYS_POWER_STATE "/sys/power/state"
35#define SYS_POWER_WAKEUP_COUNT "/sys/power/wakeup_count" 36#define SYS_POWER_WAKEUP_COUNT "/sys/power/wakeup_count"
36 37
38#define BASE_SLEEP_TIME 100000
39
37static int state_fd; 40static int state_fd;
38static int wakeup_count_fd; 41static int wakeup_count_fd;
39static pthread_t suspend_thread; 42static pthread_t suspend_thread;
40static sem_t suspend_lockout; 43static sem_t suspend_lockout;
41static const char *sleep_state = "mem"; 44static const char *sleep_state = "mem";
42static void (*wakeup_func)(bool success) = NULL; 45static void (*wakeup_func)(bool success) = NULL;
46static int sleep_time = BASE_SLEEP_TIME;
47
48static void update_sleep_time(bool success) {
49 if (success) {
50 sleep_time = BASE_SLEEP_TIME;
51 return;
52 }
53 // double sleep time after each failure up to one minute
54 sleep_time = MIN(sleep_time * 2, 60000000);
55}
43 56
44static void *suspend_thread_func(void *arg __attribute__((unused))) 57static void *suspend_thread_func(void *arg __attribute__((unused)))
45{ 58{
@@ -47,10 +60,12 @@ static void *suspend_thread_func(void *arg __attribute__((unused)))
47 char wakeup_count[20]; 60 char wakeup_count[20];
48 int wakeup_count_len; 61 int wakeup_count_len;
49 int ret; 62 int ret;
50 bool success; 63 bool success = true;
51 64
52 while (1) { 65 while (1) {
53 usleep(100000); 66 update_sleep_time(success);
67 usleep(sleep_time);
68 success = false;
54 ALOGV("%s: read wakeup_count\n", __func__); 69 ALOGV("%s: read wakeup_count\n", __func__);
55 lseek(wakeup_count_fd, 0, SEEK_SET); 70 lseek(wakeup_count_fd, 0, SEEK_SET);
56 wakeup_count_len = TEMP_FAILURE_RETRY(read(wakeup_count_fd, wakeup_count, 71 wakeup_count_len = TEMP_FAILURE_RETRY(read(wakeup_count_fd, wakeup_count,
@@ -74,7 +89,6 @@ static void *suspend_thread_func(void *arg __attribute__((unused)))
74 continue; 89 continue;
75 } 90 }
76 91
77 success = true;
78 ALOGV("%s: write %*s to wakeup_count\n", __func__, wakeup_count_len, wakeup_count); 92 ALOGV("%s: write %*s to wakeup_count\n", __func__, wakeup_count_len, wakeup_count);
79 ret = TEMP_FAILURE_RETRY(write(wakeup_count_fd, wakeup_count, wakeup_count_len)); 93 ret = TEMP_FAILURE_RETRY(write(wakeup_count_fd, wakeup_count, wakeup_count_len));
80 if (ret < 0) { 94 if (ret < 0) {
@@ -83,8 +97,8 @@ static void *suspend_thread_func(void *arg __attribute__((unused)))
83 } else { 97 } else {
84 ALOGV("%s: write %s to %s\n", __func__, sleep_state, SYS_POWER_STATE); 98 ALOGV("%s: write %s to %s\n", __func__, sleep_state, SYS_POWER_STATE);
85 ret = TEMP_FAILURE_RETRY(write(state_fd, sleep_state, strlen(sleep_state))); 99 ret = TEMP_FAILURE_RETRY(write(state_fd, sleep_state, strlen(sleep_state)));
86 if (ret < 0) { 100 if (ret >= 0) {
87 success = false; 101 success = true;
88 } 102 }
89 void (*func)(bool success) = wakeup_func; 103 void (*func)(bool success) = wakeup_func;
90 if (func != NULL) { 104 if (func != NULL) {