Refactor screen blocking logic.

Because of the call to turn on the screen introduced in ag/495255
is now made earlier we may not have sent the wakeup broadcast by
the time the windows have all drawn. In such a case onScreenOn()
did not release the wakelock and the screen stayed off.

This change ensures that no matter the timing of onScreenOn()
the wakelock will be released but only for the onScreenOn()
called in response to the most recent screen on transition.

Fixes bug 16404078.

Change-Id: Ic1e3e61e16c1fc34d4ec657e0e53ac49a05ca6a4
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index e272f38..2b4a24a 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -110,8 +110,9 @@
     // True if a user activity message should be sent.
     private boolean mUserActivityPending;
 
-    // True if the screen on blocker has been acquired.
-    private boolean mScreenOnBlockerAcquired;
+    // The currently active screen on listener. This field is non-null whenever the
+    // ScreenOnBlocker has been acquired and we are awaiting a callback to release it.
+    private ScreenOnUnblocker mPendingScreenOnUnblocker;
 
     public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
             IAppOpsService appOps, SuspendBlocker suspendBlocker, ScreenOnBlocker screenOnBlocker,
@@ -255,15 +256,16 @@
                 if (mActualPowerState != POWER_STATE_AWAKE) {
                     mActualPowerState = POWER_STATE_AWAKE;
                     mPendingWakeUpBroadcast = true;
-                    if (!mScreenOnBlockerAcquired) {
-                        mScreenOnBlockerAcquired = true;
+                    if (mPendingScreenOnUnblocker == null) {
                         mScreenOnBlocker.acquire();
                     }
+                    final ScreenOnUnblocker unblocker = new ScreenOnUnblocker();
+                    mPendingScreenOnUnblocker = unblocker;
                     mHandler.post(new Runnable() {
                         @Override
                         public void run() {
                             EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
-                            mPolicy.wakingUp(mScreenOnListener);
+                            mPolicy.wakingUp(unblocker);
                             mActivityManagerInternal.wakingUp();
                         }
                     });
@@ -459,18 +461,17 @@
         }
     }
 
-    private final WindowManagerPolicy.ScreenOnListener mScreenOnListener =
-            new WindowManagerPolicy.ScreenOnListener() {
+    private final class ScreenOnUnblocker implements WindowManagerPolicy.ScreenOnListener {
         @Override
         public void onScreenOn() {
             synchronized (mLock) {
-                if (mScreenOnBlockerAcquired && !mPendingWakeUpBroadcast) {
-                    mScreenOnBlockerAcquired = false;
+                if (mPendingScreenOnUnblocker == this) {
+                    mPendingScreenOnUnblocker = null;
                     mScreenOnBlocker.release();
                 }
             }
         }
-    };
+    }
 
     private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
         @Override