=== modified file 'src/display.c'
--- src/display.c	2013-10-10 15:35:12 +0000
+++ src/display.c	2013-12-18 22:40:08 +0000
@@ -54,6 +54,7 @@
 static gint target_brightness;
 static gint dim_brightness;
 static gboolean running_mir = FALSE;
+static gboolean earlysuspend_used = FALSE;
 
 /* Assume screen is off to start; we will force it on */
 static uuid_t internal_request_cookie;
@@ -64,6 +65,8 @@
     .flags = 0,
 };
 
+GMutex actual_screen_state_guard;
+
 /*
  * When using the proximity sensor, our actual state of the screen
  * may not match the requested state in internal_state. Therefore
@@ -77,19 +80,6 @@
  */
 static unsigned screen_off_overrides;
 
-enum fb_state {
-    FB_SLEEP,
-    FB_AWAKE,
-
-    NUM_FB_STATES
-};
-static enum fb_state fb_state = FB_AWAKE;
-
-static const char *fb_file_names[] = {
-    [FB_SLEEP] = "/sys/power/wait_for_fb_sleep",
-    [FB_AWAKE] = "/sys/power/wait_for_fb_wake"
-};
-
 static const char *display_state_strs[POWERD_NUM_DISPLAY_STATES] = {
     [POWERD_DISPLAY_STATE_DONT_CARE]    = "off",
     [POWERD_DISPLAY_STATE_ON]           = "on",
@@ -107,6 +97,10 @@
     return (flags & AB_ENABLED_MASK) == AB_ENABLED;
 }
 
+
+/* the Display Server (mir or sf) is free to fire off a few more frames as 
+   part of its shutdown process. powerd must guarantee the fb_state is FB_AWAKE,
+   and the system is not suspended until the request returns. */
 gboolean display_set_power_mode(int display, char *power_mode)
 {
     GError *error = NULL;
@@ -170,7 +164,10 @@
 
 gboolean powerd_display_enabled(void)
 {
-    return actual_screen_state == POWERD_DISPLAY_STATE_ON;
+    g_mutex_lock(&actual_screen_state_guard);
+    gboolean ret = (actual_screen_state == POWERD_DISPLAY_STATE_ON);
+    g_mutex_unlock(&actual_screen_state_guard);
+    return ret;
 }
 
 static int get_target_brightness(gboolean request_bright, int hw_value)
@@ -221,8 +218,8 @@
 
     switch (applied_state) {
     case DISPLAY_STATE_OFF:
-        if (actual_screen_state == DISPLAY_STATE_OFF) {
-            /* Nothing to do */
+        if (!powerd_display_enabled()) {
+            /* Nothing to do, display is alread off */
             return;
         }
 
@@ -230,11 +227,19 @@
         if (using_ab)
             powerd_autobrightness_disable();
         powerd_set_brightness(0);
+
         if (!display_set_power_mode(0, "off")) {
             powerd_warn("failed to set display power mode, not clearing state");
             return;
         }
 
+        if (!earlysuspend_used)
+        {
+            g_mutex_lock(&actual_screen_state_guard);
+            actual_screen_state = DISPLAY_STATE_OFF;
+            g_mutex_unlock(&actual_screen_state_guard);
+        }
+
         powerd_debug("Releasing internal active state request");
         ret = clear_sys_state_internal(internal_request_cookie);
         if (!ret) {
@@ -245,7 +250,8 @@
         }
         break;
     case POWERD_DISPLAY_STATE_ON:
-        if (actual_screen_state != POWERD_DISPLAY_STATE_ON) {
+        if (!powerd_display_enabled()) {
+            /* display is off, must turn display on */
             powerd_debug("Requesting active state internally");
             ret = request_sys_state_internal("display-request",
                                              POWERD_SYS_STATE_ACTIVE,
@@ -253,16 +259,18 @@
             if (!ret)
                 powerd_warn("Request for active state failed");
 
-            /*
-             * If the current state is suspend we need to wait for
-             * notification of leaving the active state, otherwise the
-             * screen may fail to turn on for devices using earlysuspend.
-             * Otherwise we can turn on the screen right away.
-             */
-            if (fb_state == FB_AWAKE)
+            /* if the device uses earlysuspend, responsibility for turning
+               the display server and changing actual_screen_state falls
+               to wait_for_fb_thread() */
+            if (!earlysuspend_used)
+            {
                 turn_on_display(use_ab);
+                g_mutex_lock(&actual_screen_state_guard);
+                actual_screen_state = POWERD_DISPLAY_STATE_ON;
+                g_mutex_unlock(&actual_screen_state_guard);
+            }
         } else {
-            /* Only changing brightness */
+            /* display is already on, must only changing brightness */
             if (use_ab) {
                 if (!using_ab)
                     powerd_autobrightness_enable();
@@ -281,8 +289,6 @@
         powerd_warn("Invalid display state %d", applied_state);
         return;
     }
-
-    actual_screen_state = applied_state;
 }
 
 static void update_flags(guint32 flags)
@@ -389,7 +395,6 @@
     powerd_run_mainloop_sync(apply_override_worker, &ovr_data);
 }
 
-
 static int wait_for_file(const char *fname)
 {
     int fd, ret;
@@ -407,31 +412,43 @@
     return ret == -1 ? -errno : 0;
 }
 
-static gboolean fb_state_changed(gpointer data)
-{
-    fb_state = (enum fb_state)data;
-    powerd_debug("fb state %s", fb_state == FB_SLEEP ? "sleep" : "awake");
-    if (fb_state == FB_AWAKE && powerd_display_enabled())
-        turn_on_display(ab_enabled(internal_state.flags));
-    return FALSE;
-}
+enum fb_state {
+    FB_SLEEP,
+    FB_AWAKE,
+
+    NUM_FB_STATES
+};
+
+static const char *fb_file_names[] = {
+    [FB_SLEEP] = "/sys/power/wait_for_fb_sleep",
+    [FB_AWAKE] = "/sys/power/wait_for_fb_wake"
+};
 
 static gpointer wait_for_fb_thread(gpointer unused)
 {
-    unsigned long state = fb_state;
-
-    if (state >= NUM_FB_STATES) {
-        powerd_warn("Invalid FB state");
-        return NULL;
-    }
-
+    enum fb_state fb_state = FB_AWAKE;
     while (1) {
-        state = (state == FB_SLEEP) ? FB_AWAKE : FB_SLEEP;
-        if (wait_for_file(fb_file_names[state])) {
-            powerd_warn("Error reading %s", fb_file_names[state]);
+        enum fb_state next_state = (fb_state == FB_SLEEP) ? FB_AWAKE : FB_SLEEP;
+
+        if (wait_for_file(fb_file_names[next_state])) {
+            powerd_warn("Error reading %s", fb_file_names[next_state]);
             return NULL;
         }
-        g_timeout_add(0, fb_state_changed, (gpointer)state);
+
+        fb_state = next_state;
+        powerd_debug("fb state %s", fb_state == FB_SLEEP ? "sleep" : "awake");
+
+        g_mutex_lock(&actual_screen_state_guard);
+        if (fb_state == FB_AWAKE) 
+        {
+            turn_on_display(ab_enabled(internal_state.flags));
+            actual_screen_state = POWERD_DISPLAY_STATE_ON;
+        }
+        else if (fb_state == FB_SLEEP)
+        {
+            actual_screen_state = DISPLAY_STATE_OFF;
+        }
+        g_mutex_unlock(&actual_screen_state_guard);
     }
     return NULL;
 }
@@ -489,7 +506,15 @@
 
     /* If kernel supports earlysuspend, start thread to monitor fb state */
     if (!access(fb_file_names[FB_SLEEP], F_OK))
+    {
+        powerd_debug("device uses earlysuspend");
+        earlysuspend_used = TRUE;
         g_thread_new("powerd_fb_wake_monitor", wait_for_fb_thread, &error);
+    } else
+    {
+        powerd_debug("device does not use earlysuspend");
+        earlysuspend_used = FALSE;
+    }
 
     return 0;
 }

