From f25dd878dfeba87a3c2b868e07cb550061f670b4 Mon Sep 17 00:00:00 2001 From: Colin Cross Date: Thu, 14 Jun 2012 12:55:47 -0700 Subject: [PATCH] libsuspend: wait for earlysuspend transition to finish Wait for the early suspend transition to finish to the point where surfaceflinger would previously have synchronized. This is important during screen on, to ensure the display early suspend handlers have completed before surfaceflinger unblanks. Change-Id: I91ac0253d9655c3f1ae3dd7f1a918c279568b23e --- libsuspend/autosuspend_earlysuspend.c | 42 +++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/libsuspend/autosuspend_earlysuspend.c b/libsuspend/autosuspend_earlysuspend.c index b4401284c..1df8c6a13 100644 --- a/libsuspend/autosuspend_earlysuspend.c +++ b/libsuspend/autosuspend_earlysuspend.c @@ -16,6 +16,8 @@ #include #include +#include +#include #include #include #include @@ -31,11 +33,17 @@ #define EARLYSUSPEND_WAIT_FOR_FB_SLEEP "/sys/power/wait_for_fb_sleep" #define EARLYSUSPEND_WAIT_FOR_FB_WAKE "/sys/power/wait_for_fb_wake" - static int sPowerStatefd; static const char *pwr_state_mem = "mem"; static const char *pwr_state_on = "on"; static pthread_t earlysuspend_thread; +static pthread_mutex_t earlysuspend_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t earlysuspend_cond = PTHREAD_COND_INITIALIZER; +static bool wait_for_earlysuspend; +static enum { + EARLYSUSPEND_ON, + EARLYSUSPEND_MEM, +} earlysuspend_state = EARLYSUSPEND_ON; int wait_for_fb_wake(void) { @@ -79,10 +87,19 @@ static void *earlysuspend_thread_func(void *arg) ALOGE("Failed reading wait_for_fb_sleep, exiting earlysuspend thread\n"); return NULL; } + pthread_mutex_lock(&earlysuspend_mutex); + earlysuspend_state = EARLYSUSPEND_MEM; + pthread_cond_signal(&earlysuspend_cond); + pthread_mutex_unlock(&earlysuspend_mutex); + if (wait_for_fb_wake()) { ALOGE("Failed reading wait_for_fb_wake, exiting earlysuspend thread\n"); return NULL; } + pthread_mutex_lock(&earlysuspend_mutex); + earlysuspend_state = EARLYSUSPEND_ON; + pthread_cond_signal(&earlysuspend_cond); + pthread_mutex_unlock(&earlysuspend_mutex); } } static int autosuspend_earlysuspend_enable(void) @@ -99,6 +116,14 @@ static int autosuspend_earlysuspend_enable(void) goto err; } + if (wait_for_earlysuspend) { + pthread_mutex_lock(&earlysuspend_mutex); + while (earlysuspend_state != EARLYSUSPEND_MEM) { + pthread_cond_wait(&earlysuspend_cond, &earlysuspend_mutex); + } + pthread_mutex_unlock(&earlysuspend_mutex); + } + ALOGV("autosuspend_earlysuspend_enable done\n"); return 0; @@ -121,6 +146,14 @@ static int autosuspend_earlysuspend_disable(void) goto err; } + if (wait_for_earlysuspend) { + pthread_mutex_lock(&earlysuspend_mutex); + while (earlysuspend_state != EARLYSUSPEND_ON) { + pthread_cond_wait(&earlysuspend_cond, &earlysuspend_mutex); + } + pthread_mutex_unlock(&earlysuspend_mutex); + } + ALOGV("autosuspend_earlysuspend_disable done\n"); return 0; @@ -149,12 +182,17 @@ void start_earlysuspend_thread(void) return; } + wait_for_fb_wake(); + 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)); + strerror_r(errno, buf, sizeof(buf)); ALOGE("Error creating thread: %s\n", buf); + return; } + + wait_for_earlysuspend = true; } struct autosuspend_ops *autosuspend_earlysuspend_init(void)