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)