diff options
author | Colin Cross <ccross@android.com> | 2012-06-07 14:12:54 -0700 |
---|---|---|
committer | Colin Cross <ccross@android.com> | 2012-06-07 17:15:17 -0700 |
commit | 2146b7f2d7f8e9320d8ec5581c61e14f243ee97c (patch) | |
tree | cd0d7d434ae6392710c4a732f4c9e0ad34b8129d /libsuspend | |
parent | 6ba76f019040a0445575deb6995cd32ea72903dd (diff) | |
download | system_core-2146b7f2d7f8e9320d8ec5581c61e14f243ee97c.zip system_core-2146b7f2d7f8e9320d8ec5581c61e14f243ee97c.tar.gz system_core-2146b7f2d7f8e9320d8ec5581c61e14f243ee97c.tar.bz2 |
libsuspend: always unblock early suspend
SurfaceFlinger and PowerManagerService manage their synchronization
without the help of early suspend, and SurfaceFlinger no longer unblocks
early suspend. Add a new thread when early suspend is detected that will
immediately unblock early suspend.
Change-Id: I87ef4984a2ab34cbbb3af8b7762236b9a92dc2ea
Diffstat (limited to 'libsuspend')
-rw-r--r-- | libsuspend/autosuspend_earlysuspend.c | 84 |
1 files changed, 80 insertions, 4 deletions
diff --git a/libsuspend/autosuspend_earlysuspend.c b/libsuspend/autosuspend_earlysuspend.c index 2c2aa36..b440128 100644 --- a/libsuspend/autosuspend_earlysuspend.c +++ b/libsuspend/autosuspend_earlysuspend.c @@ -35,7 +35,56 @@ static int sPowerStatefd; static const char *pwr_state_mem = "mem"; static const char *pwr_state_on = "on"; +static pthread_t earlysuspend_thread; +int wait_for_fb_wake(void) +{ + int err = 0; + char buf; + int fd = open(EARLYSUSPEND_WAIT_FOR_FB_WAKE, O_RDONLY, 0); + // if the file doesn't exist, the error will be caught in read() below + do { + err = read(fd, &buf, 1); + } while (err < 0 && errno == EINTR); + ALOGE_IF(err < 0, + "*** ANDROID_WAIT_FOR_FB_WAKE failed (%s)", strerror(errno)); + close(fd); + return err < 0 ? err : 0; +} + +static int wait_for_fb_sleep(void) +{ + int err = 0; + char buf; + int fd = open(EARLYSUSPEND_WAIT_FOR_FB_SLEEP, O_RDONLY, 0); + // if the file doesn't exist, the error will be caught in read() below + do { + err = read(fd, &buf, 1); + } while (err < 0 && errno == EINTR); + ALOGE_IF(err < 0, + "*** ANDROID_WAIT_FOR_FB_SLEEP failed (%s)", strerror(errno)); + close(fd); + return err < 0 ? err : 0; +} + +static void *earlysuspend_thread_func(void *arg) +{ + char buf[80]; + char wakeup_count[20]; + int wakeup_count_len; + int ret; + + while (1) { + if (wait_for_fb_sleep()) { + ALOGE("Failed reading wait_for_fb_sleep, exiting earlysuspend thread\n"); + return NULL; + } + if (wait_for_fb_wake()) { + ALOGE("Failed reading wait_for_fb_wake, exiting earlysuspend thread\n"); + return NULL; + } + } +} static int autosuspend_earlysuspend_enable(void) { char buf[80]; @@ -85,29 +134,56 @@ struct autosuspend_ops autosuspend_earlysuspend_ops = { .disable = autosuspend_earlysuspend_disable, }; -struct autosuspend_ops *autosuspend_earlysuspend_init(void) +void start_earlysuspend_thread(void) { char buf[80]; int ret; ret = access(EARLYSUSPEND_WAIT_FOR_FB_SLEEP, F_OK); if (ret < 0) { - return NULL; + return; } ret = access(EARLYSUSPEND_WAIT_FOR_FB_WAKE, F_OK); if (ret < 0) { - return NULL; + return; } + ALOGI("Starting early suspend unblocker thread\n"); + ret = pthread_create(&earlysuspend_thread, NULL, earlysuspend_thread_func, NULL); + if (ret) { + strerror_r(ret, buf, sizeof(buf)); + ALOGE("Error creating thread: %s\n", buf); + } +} + +struct autosuspend_ops *autosuspend_earlysuspend_init(void) +{ + char buf[80]; + int ret; + sPowerStatefd = open(EARLYSUSPEND_SYS_POWER_STATE, O_RDWR); if (sPowerStatefd < 0) { strerror_r(errno, buf, sizeof(buf)); - ALOGE("Error opening %s: %s\n", EARLYSUSPEND_SYS_POWER_STATE, buf); + ALOGW("Error opening %s: %s\n", EARLYSUSPEND_SYS_POWER_STATE, buf); return NULL; } + ret = write(sPowerStatefd, "on", 2); + if (ret < 0) { + strerror_r(errno, buf, sizeof(buf)); + ALOGW("Error writing 'on' to %s: %s\n", EARLYSUSPEND_SYS_POWER_STATE, buf); + goto err_write; + } + ALOGI("Selected early suspend\n"); + + start_earlysuspend_thread(); + return &autosuspend_earlysuspend_ops; + +err_write: + close(sPowerStatefd); + return NULL; } |