Plumb display power state through display manager.

Declare a new method, Display.getState() to retrieve the actual
power state of a display.

Improved documentation for Intent.ACTION_SCREEN_ON and
Intent.ACTION_SCREEN_OFF to clarify what they really mean in
terms of the interactive state of the device.

Deprecated PowerManager.isScreenOn() and replaced it with
PowerManager.isInteractive() with a more suggestive name and
better documentation.

Redirect display power state changes to go through the display
manager first and only then head over to the power manager for
legacy compatibility.

Eliminated the bright here and woke here policy flags since they
were unused.  Simplified the input dispatch policy somewhat.

Ensure that screen wake locks are respected up until the point
when dozing really begins.

Fixed a regression in DreamService where onDreamingStarted
might be called before onWindowAttached.

Bug: 13133142
Bug: 13472578
Bug: 13929355
Bug: 13760290
Change-Id: Iabef96921dd554ce3768fb18619cefc3230b5fb0
diff --git a/services/core/java/com/android/server/display/DisplayBlanker.java b/services/core/java/com/android/server/display/DisplayBlanker.java
new file mode 100644
index 0000000..eb0ae6a
--- /dev/null
+++ b/services/core/java/com/android/server/display/DisplayBlanker.java
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display;
+
+/**
+ * Interface used to update the actual display state.
+ */
+public interface DisplayBlanker {
+    void requestDisplayState(int state);
+}
diff --git a/services/core/java/com/android/server/display/DisplayDevice.java b/services/core/java/com/android/server/display/DisplayDevice.java
index 9ec1122..a5f9822 100644
--- a/services/core/java/com/android/server/display/DisplayDevice.java
+++ b/services/core/java/com/android/server/display/DisplayDevice.java
@@ -107,15 +107,9 @@
     }
 
     /**
-     * Blanks the display, if supported.
+     * Sets the display state, if supported.
      */
-    public void blankLocked() {
-    }
-
-    /**
-     * Unblanks the display, if supported.
-     */
-    public void unblankLocked() {
+    public void requestDisplayStateLocked(int state) {
     }
 
     /**
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index 75f1f53..a77443d 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -176,6 +176,11 @@
     public String address;
 
     /**
+     * Display state.
+     */
+    public int state = Display.STATE_ON;
+
+    /**
      * The UID of the application that owns this display, or zero if it is owned by the system.
      * <p>
      * If the display is private, then only the owner can use it.
@@ -219,6 +224,7 @@
                 && rotation == other.rotation
                 && type == other.type
                 && Objects.equal(address, other.address)
+                && state == other.state
                 && ownerUid == other.ownerUid
                 && Objects.equal(ownerPackageName, other.ownerPackageName);
     }
@@ -241,6 +247,7 @@
         rotation = other.rotation;
         type = other.type;
         address = other.address;
+        state = other.state;
         ownerUid = other.ownerUid;
         ownerPackageName = other.ownerPackageName;
     }
@@ -260,6 +267,7 @@
         if (address != null) {
             sb.append(", address ").append(address);
         }
+        sb.append(", state ").append(Display.stateToString(state));
         if (ownerUid != 0 || ownerPackageName != null) {
             sb.append(", owner ").append(ownerPackageName);
             sb.append(" (uid ").append(ownerUid).append(")");
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 693f7d8..071417b 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -121,10 +121,6 @@
     private static final int MSG_REQUEST_TRAVERSAL = 4;
     private static final int MSG_UPDATE_VIEWPORT = 5;
 
-    private static final int DISPLAY_BLANK_STATE_UNKNOWN = 0;
-    private static final int DISPLAY_BLANK_STATE_BLANKED = 1;
-    private static final int DISPLAY_BLANK_STATE_UNBLANKED = 2;
-
     private final Context mContext;
     private final DisplayManagerHandler mHandler;
     private final Handler mUiHandler;
@@ -176,8 +172,9 @@
     // Display power controller.
     private DisplayPowerController mDisplayPowerController;
 
-    // Set to true if all displays have been blanked by the power manager.
-    private int mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNKNOWN;
+    // The overall display state, independent of changes that might influence one
+    // display or another in particular.
+    private int mGlobalDisplayState = Display.STATE_UNKNOWN;
 
     // Set to true when there are pending display changes that have yet to be applied
     // to the surface flinger state.
@@ -315,21 +312,11 @@
         }
     }
 
-    private void blankAllDisplaysFromPowerManagerInternal() {
+    private void requestGlobalDisplayStateInternal(int state) {
         synchronized (mSyncRoot) {
-            if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_BLANKED) {
-                mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_BLANKED;
-                updateAllDisplayBlankingLocked();
-                scheduleTraversalLocked(false);
-            }
-        }
-    }
-
-    private void unblankAllDisplaysFromPowerManagerInternal() {
-        synchronized (mSyncRoot) {
-            if (mAllDisplayBlankStateFromPowerManager != DISPLAY_BLANK_STATE_UNBLANKED) {
-                mAllDisplayBlankStateFromPowerManager = DISPLAY_BLANK_STATE_UNBLANKED;
-                updateAllDisplayBlankingLocked();
+            if (mGlobalDisplayState != state) {
+                mGlobalDisplayState = state;
+                updateGlobalDisplayStateLocked();
                 scheduleTraversalLocked(false);
             }
         }
@@ -616,7 +603,7 @@
 
         mDisplayDevices.add(device);
         addLogicalDisplayLocked(device);
-        updateDisplayBlankingLocked(device);
+        updateDisplayStateLocked(device);
         scheduleTraversalLocked(false);
     }
 
@@ -655,27 +642,20 @@
         scheduleTraversalLocked(false);
     }
 
-    private void updateAllDisplayBlankingLocked() {
+    private void updateGlobalDisplayStateLocked() {
         final int count = mDisplayDevices.size();
         for (int i = 0; i < count; i++) {
             DisplayDevice device = mDisplayDevices.get(i);
-            updateDisplayBlankingLocked(device);
+            updateDisplayStateLocked(device);
         }
     }
 
-    private void updateDisplayBlankingLocked(DisplayDevice device) {
+    private void updateDisplayStateLocked(DisplayDevice device) {
         // Blank or unblank the display immediately to match the state requested
-        // by the power manager (if known).
+        // by the display power controller (if known).
         DisplayDeviceInfo info = device.getDisplayDeviceInfoLocked();
         if ((info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0) {
-            switch (mAllDisplayBlankStateFromPowerManager) {
-                case DISPLAY_BLANK_STATE_BLANKED:
-                    device.blankLocked();
-                    break;
-                case DISPLAY_BLANK_STATE_UNBLANKED:
-                    device.unblankLocked();
-                    break;
-            }
+            device.requestDisplayStateLocked(mGlobalDisplayState);
         }
     }
 
@@ -816,9 +796,7 @@
                     + device.getDisplayDeviceInfoLocked());
             return;
         }
-        boolean isBlanked = (mAllDisplayBlankStateFromPowerManager == DISPLAY_BLANK_STATE_BLANKED)
-                && (info.flags & DisplayDeviceInfo.FLAG_NEVER_BLANK) == 0;
-        display.configureDisplayInTransactionLocked(device, isBlanked);
+        display.configureDisplayInTransactionLocked(device, info.state == Display.STATE_OFF);
 
         // Update the viewports if needed.
         if (!mDefaultViewport.valid
@@ -897,8 +875,7 @@
             pw.println("  mOnlyCode=" + mOnlyCore);
             pw.println("  mSafeMode=" + mSafeMode);
             pw.println("  mPendingTraversal=" + mPendingTraversal);
-            pw.println("  mAllDisplayBlankStateFromPowerManager="
-                    + mAllDisplayBlankStateFromPowerManager);
+            pw.println("  mGlobalDisplayState=" + Display.stateToString(mGlobalDisplayState));
             pw.println("  mNextNonDefaultDisplayId=" + mNextNonDefaultDisplayId);
             pw.println("  mDefaultViewport=" + mDefaultViewport);
             pw.println("  mExternalTouchViewport=" + mExternalTouchViewport);
@@ -1322,11 +1299,26 @@
 
     private final class LocalService extends DisplayManagerInternal {
         @Override
-        public void initPowerManagement(DisplayPowerCallbacks callbacks, Handler handler,
+        public void initPowerManagement(final DisplayPowerCallbacks callbacks, Handler handler,
                 SensorManager sensorManager) {
             synchronized (mSyncRoot) {
+                DisplayBlanker blanker = new DisplayBlanker() {
+                    @Override
+                    public void requestDisplayState(int state) {
+                        // The order of operations is important for legacy reasons.
+                        if (state == Display.STATE_OFF) {
+                            requestGlobalDisplayStateInternal(state);
+                        }
+
+                        callbacks.onDisplayStateChange(state);
+
+                        if (state != Display.STATE_OFF) {
+                            requestGlobalDisplayStateInternal(state);
+                        }
+                    }
+                };
                 mDisplayPowerController = new DisplayPowerController(
-                        mContext, callbacks, handler, sensorManager);
+                        mContext, callbacks, handler, sensorManager, blanker);
             }
         }
 
@@ -1343,16 +1335,6 @@
         }
 
         @Override
-        public void blankAllDisplaysFromPowerManager() {
-            blankAllDisplaysFromPowerManagerInternal();
-        }
-
-        @Override
-        public void unblankAllDisplaysFromPowerManager() {
-            unblankAllDisplaysFromPowerManagerInternal();
-        }
-
-        @Override
         public DisplayInfo getDisplayInfo(int displayId) {
             return getDisplayInfoInternal(displayId, Process.myUid());
         }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index dcf7da2..7abf88c 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -45,6 +45,7 @@
 import android.util.Slog;
 import android.util.Spline;
 import android.util.TimeUtils;
+import android.view.Display;
 
 import java.io.PrintWriter;
 
@@ -185,6 +186,9 @@
     // The sensor manager.
     private final SensorManager mSensorManager;
 
+    // The display blanker.
+    private final DisplayBlanker mBlanker;
+
     // The proximity sensor, or null if not available or needed.
     private Sensor mProximitySensor;
 
@@ -349,7 +353,8 @@
      * Creates the display power controller.
      */
     public DisplayPowerController(Context context,
-            DisplayPowerCallbacks callbacks, Handler handler, SensorManager sensorManager) {
+            DisplayPowerCallbacks callbacks, Handler handler,
+            SensorManager sensorManager, DisplayBlanker blanker) {
         mHandler = new DisplayControllerHandler(handler.getLooper());
         mCallbacks = callbacks;
 
@@ -357,6 +362,7 @@
         mLights = LocalServices.getService(LightsManager.class);
         mTwilight = LocalServices.getService(TwilightManager.class);
         mSensorManager = sensorManager;
+        mBlanker = blanker;
 
         final Resources resources = context.getResources();
 
@@ -520,8 +526,11 @@
     }
 
     private void initialize() {
-        mPowerState = new DisplayPowerState(new ElectronBeam(), mCallbacks,
-                mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT));
+        // Initialize the power state object for the default display.
+        // In the future, we might manage multiple displays independently.
+        mPowerState = new DisplayPowerState(mBlanker,
+                mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT),
+                new ElectronBeam(Display.DEFAULT_DISPLAY));
 
         mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
                 mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f);
@@ -670,7 +679,7 @@
         // Animate the screen on or off unless blocked.
         if (mScreenOffBecauseOfProximity) {
             // Screen off due to proximity.
-            setScreenOn(false);
+            setScreenState(Display.STATE_OFF);
             unblockScreenOn();
         } else if (mPowerRequest.wantScreenOnAny()) {
             // Want screen on.
@@ -681,7 +690,8 @@
                 // Turn the screen on.  The contents of the screen may not yet
                 // be visible if the electron beam has not been dismissed because
                 // its last frame of animation is solid black.
-                setScreenOn(true);
+                setScreenState(mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE
+                        ? Display.STATE_DOZING : Display.STATE_ON);
 
                 if (mPowerRequest.blockScreenOn
                         && mPowerState.getElectronBeamLevel() == 0.0f) {
@@ -714,12 +724,12 @@
             if (!mElectronBeamOnAnimator.isStarted()) {
                 if (!mElectronBeamOffAnimator.isStarted()) {
                     if (mPowerState.getElectronBeamLevel() == 0.0f) {
-                        setScreenOn(false);
+                        setScreenState(Display.STATE_OFF);
                     } else if (mPowerState.prepareElectronBeam(
                             mElectronBeamFadesConfig ?
                                     ElectronBeam.MODE_FADE :
                                             ElectronBeam.MODE_COOL_DOWN)
-                            && mPowerState.isScreenOn()) {
+                            && mPowerState.getScreenState() != Display.STATE_OFF) {
                         mElectronBeamOffAnimator.start();
                     } else {
                         mElectronBeamOffAnimator.end();
@@ -752,9 +762,9 @@
     private void blockScreenOn() {
         if (!mScreenOnWasBlocked) {
             mScreenOnWasBlocked = true;
+            mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
             if (DEBUG) {
                 Slog.d(TAG, "Blocked screen on.");
-                mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
             }
         }
     }
@@ -769,11 +779,11 @@
         }
     }
 
-    private void setScreenOn(boolean on) {
-        if (mPowerState.isScreenOn() != on) {
-            mPowerState.setScreenOn(on);
+    private void setScreenState(int state) {
+        if (mPowerState.getScreenState() != state) {
+            mPowerState.setScreenState(state);
             try {
-                if (on) {
+                if (state != Display.STATE_OFF) {
                     mBatteryStats.noteScreenOn();
                 } else {
                     mBatteryStats.noteScreenOff();
diff --git a/services/core/java/com/android/server/display/DisplayPowerState.java b/services/core/java/com/android/server/display/DisplayPowerState.java
index e1416d7..a5f8849 100644
--- a/services/core/java/com/android/server/display/DisplayPowerState.java
+++ b/services/core/java/com/android/server/display/DisplayPowerState.java
@@ -18,7 +18,6 @@
 
 import com.android.server.lights.Light;
 
-import android.hardware.display.DisplayManagerInternal.DisplayPowerCallbacks;
 import android.os.AsyncTask;
 import android.os.Handler;
 import android.os.Looper;
@@ -27,6 +26,7 @@
 import android.util.IntProperty;
 import android.util.Slog;
 import android.view.Choreographer;
+import android.view.Display;
 
 import java.io.PrintWriter;
 
@@ -54,12 +54,12 @@
 
     private final Handler mHandler;
     private final Choreographer mChoreographer;
-    private final ElectronBeam mElectronBeam;
-    private final DisplayPowerCallbacks mCallbacks;
+    private final DisplayBlanker mBlanker;
     private final Light mBacklight;
+    private final ElectronBeam mElectronBeam;
     private final PhotonicModulator mPhotonicModulator;
 
-    private boolean mScreenOn;
+    private int mScreenState;
     private int mScreenBrightness;
     private boolean mScreenReady;
     private boolean mScreenUpdatePending;
@@ -71,13 +71,12 @@
 
     private Runnable mCleanListener;
 
-    public DisplayPowerState(ElectronBeam electronBean,
-            DisplayPowerCallbacks callbacks, Light backlight) {
+    public DisplayPowerState(DisplayBlanker blanker, Light backlight, ElectronBeam electronBeam) {
         mHandler = new Handler(true /*async*/);
         mChoreographer = Choreographer.getInstance();
-        mElectronBeam = electronBean;
-        mCallbacks = callbacks;
+        mBlanker = blanker;
         mBacklight = backlight;
+        mElectronBeam = electronBeam;
         mPhotonicModulator = new PhotonicModulator();
 
         // At boot time, we know that the screen is on and the electron beam
@@ -86,7 +85,7 @@
         // Although we set the brightness to full on here, the display power controller
         // will reset the brightness to a new level immediately before the changes
         // actually have a chance to be applied.
-        mScreenOn = true;
+        mScreenState = Display.STATE_ON;
         mScreenBrightness = PowerManager.BRIGHTNESS_ON;
         scheduleScreenUpdate();
 
@@ -122,25 +121,25 @@
     };
 
     /**
-     * Sets whether the screen is on or off.
+     * Sets whether the screen is on, off, or dozing.
      */
-    public void setScreenOn(boolean on) {
-        if (mScreenOn != on) {
+    public void setScreenState(int state) {
+        if (mScreenState != state) {
             if (DEBUG) {
-                Slog.d(TAG, "setScreenOn: on=" + on);
+                Slog.d(TAG, "setScreenState: state=" + state);
             }
 
-            mScreenOn = on;
+            mScreenState = state;
             mScreenReady = false;
             scheduleScreenUpdate();
         }
     }
 
     /**
-     * Returns true if the screen is on.
+     * Gets the desired screen state.
      */
-    public boolean isScreenOn() {
-        return mScreenOn;
+    public int getScreenState() {
+        return mScreenState;
     }
 
     /**
@@ -155,7 +154,7 @@
             }
 
             mScreenBrightness = brightness;
-            if (mScreenOn) {
+            if (mScreenState != Display.STATE_OFF) {
                 mScreenReady = false;
                 scheduleScreenUpdate();
             }
@@ -219,7 +218,7 @@
             }
 
             mElectronBeamLevel = level;
-            if (mScreenOn) {
+            if (mScreenState != Display.STATE_OFF) {
                 mScreenReady = false;
                 scheduleScreenUpdate(); // update backlight brightness
             }
@@ -256,7 +255,7 @@
     public void dump(PrintWriter pw) {
         pw.println();
         pw.println("Display Power State:");
-        pw.println("  mScreenOn=" + mScreenOn);
+        pw.println("  mScreenState=" + Display.stateToString(mScreenState));
         pw.println("  mScreenBrightness=" + mScreenBrightness);
         pw.println("  mScreenReady=" + mScreenReady);
         pw.println("  mScreenUpdatePending=" + mScreenUpdatePending);
@@ -302,8 +301,9 @@
         public void run() {
             mScreenUpdatePending = false;
 
-            int brightness = mScreenOn && mElectronBeamLevel > 0f ? mScreenBrightness : 0;
-            if (mPhotonicModulator.setState(mScreenOn, brightness)) {
+            int brightness = mScreenState != Display.STATE_OFF
+                    && mElectronBeamLevel > 0f ? mScreenBrightness : 0;
+            if (mPhotonicModulator.setState(mScreenState, brightness)) {
                 if (DEBUG) {
                     Slog.d(TAG, "Screen ready");
                 }
@@ -335,26 +335,26 @@
      * Updates the state of the screen and backlight asynchronously on a separate thread.
      */
     private final class PhotonicModulator {
-        private static final boolean INITIAL_SCREEN_ON = false; // unknown, assume off
+        private static final int INITIAL_SCREEN_STATE = Display.STATE_OFF; // unknown, assume off
         private static final int INITIAL_BACKLIGHT = -1; // unknown
 
         private final Object mLock = new Object();
 
-        private boolean mPendingOn = INITIAL_SCREEN_ON;
+        private int mPendingState = INITIAL_SCREEN_STATE;
         private int mPendingBacklight = INITIAL_BACKLIGHT;
-        private boolean mActualOn = INITIAL_SCREEN_ON;
+        private int mActualState = INITIAL_SCREEN_STATE;
         private int mActualBacklight = INITIAL_BACKLIGHT;
         private boolean mChangeInProgress;
 
-        public boolean setState(boolean on, int backlight) {
+        public boolean setState(int state, int backlight) {
             synchronized (mLock) {
-                if (on != mPendingOn || backlight != mPendingBacklight) {
+                if (state != mPendingState || backlight != mPendingBacklight) {
                     if (DEBUG) {
-                        Slog.d(TAG, "Requesting new screen state: on=" + on
-                                + ", backlight=" + backlight);
+                        Slog.d(TAG, "Requesting new screen state: state="
+                                + Display.stateToString(state) + ", backlight=" + backlight);
                     }
 
-                    mPendingOn = on;
+                    mPendingState = state;
                     mPendingBacklight = backlight;
 
                     if (!mChangeInProgress) {
@@ -369,9 +369,9 @@
         public void dump(PrintWriter pw) {
             pw.println();
             pw.println("Photonic Modulator State:");
-            pw.println("  mPendingOn=" + mPendingOn);
+            pw.println("  mPendingState=" + Display.stateToString(mPendingState));
             pw.println("  mPendingBacklight=" + mPendingBacklight);
-            pw.println("  mActualOn=" + mActualOn);
+            pw.println("  mActualState=" + Display.stateToString(mActualState));
             pw.println("  mActualBacklight=" + mActualBacklight);
             pw.println("  mChangeInProgress=" + mChangeInProgress);
         }
@@ -381,35 +381,35 @@
             public void run() {
                 // Apply pending changes until done.
                 for (;;) {
-                    final boolean on;
-                    final boolean onChanged;
+                    final int state;
+                    final boolean stateChanged;
                     final int backlight;
                     final boolean backlightChanged;
                     synchronized (mLock) {
-                        on = mPendingOn;
-                        onChanged = (on != mActualOn);
+                        state = mPendingState;
+                        stateChanged = (state != mActualState);
                         backlight = mPendingBacklight;
                         backlightChanged = (backlight != mActualBacklight);
-                        if (!onChanged && !backlightChanged) {
+                        if (!stateChanged && !backlightChanged) {
                             mChangeInProgress = false;
                             break;
                         }
-                        mActualOn = on;
+                        mActualState = state;
                         mActualBacklight = backlight;
                     }
 
                     if (DEBUG) {
-                        Slog.d(TAG, "Updating screen state: on=" + on
-                                + ", backlight=" + backlight);
+                        Slog.d(TAG, "Updating screen state: state="
+                                + Display.stateToString(state) + ", backlight=" + backlight);
                     }
-                    if (onChanged && on) {
-                        mCallbacks.unblankAllDisplays();
+                    if (stateChanged && state != Display.STATE_OFF) {
+                        mBlanker.requestDisplayState(state);
                     }
                     if (backlightChanged) {
                         mBacklight.setBrightness(backlight);
                     }
-                    if (onChanged && !on) {
-                        mCallbacks.blankAllDisplays();
+                    if (stateChanged && state == Display.STATE_OFF) {
+                        mBlanker.requestDisplayState(state);
                     }
                 }
 
diff --git a/services/core/java/com/android/server/display/ElectronBeam.java b/services/core/java/com/android/server/display/ElectronBeam.java
index 13816bb..18e4049 100644
--- a/services/core/java/com/android/server/display/ElectronBeam.java
+++ b/services/core/java/com/android/server/display/ElectronBeam.java
@@ -35,7 +35,6 @@
 import android.os.Looper;
 import android.util.FloatMath;
 import android.util.Slog;
-import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface.OutOfResourcesException;
 import android.view.Surface;
@@ -74,6 +73,8 @@
     // See code for details.
     private static final int DEJANK_FRAMES = 3;
 
+    private final int mDisplayId;
+
     // Set to true when the animation context has been fully prepared.
     private boolean mPrepared;
     private int mMode;
@@ -118,8 +119,8 @@
      */
     public static final int MODE_FADE = 2;
 
-
-    public ElectronBeam() {
+    public ElectronBeam(int displayId) {
+        mDisplayId = displayId;
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
     }
 
@@ -139,7 +140,7 @@
 
         // Get the display size and layer stack.
         // This is not expected to change while the electron beam surface is showing.
-        DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY);
+        DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(mDisplayId);
         mDisplayLayerStack = displayInfo.layerStack;
         mDisplayWidth = displayInfo.getNaturalWidth();
         mDisplayHeight = displayInfo.getNaturalHeight();
@@ -528,7 +529,8 @@
             mSurface = new Surface();
             mSurface.copyFrom(mSurfaceControl);
 
-            mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal, mSurfaceControl);
+            mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal,
+                    mDisplayId, mSurfaceControl);
             mSurfaceLayout.onDisplayTransaction();
         } finally {
             SurfaceControl.closeTransaction();
@@ -687,11 +689,13 @@
      */
     private static final class NaturalSurfaceLayout implements DisplayTransactionListener {
         private final DisplayManagerInternal mDisplayManagerInternal;
+        private final int mDisplayId;
         private SurfaceControl mSurfaceControl;
 
         public NaturalSurfaceLayout(DisplayManagerInternal displayManagerInternal,
-                SurfaceControl surfaceControl) {
+                int displayId, SurfaceControl surfaceControl) {
             mDisplayManagerInternal = displayManagerInternal;
+            mDisplayId = displayId;
             mSurfaceControl = surfaceControl;
             mDisplayManagerInternal.registerDisplayTransactionListener(this);
         }
@@ -710,8 +714,7 @@
                     return;
                 }
 
-                DisplayInfo displayInfo =
-                        mDisplayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY);
+                DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(mDisplayId);
                 switch (displayInfo.rotation) {
                     case Surface.ROTATION_0:
                         mSurfaceControl.setPosition(0, 0);
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index cb8f3e2..b8bf484 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -102,7 +102,7 @@
 
         private DisplayDeviceInfo mInfo;
         private boolean mHavePendingChanges;
-        private boolean mBlanked;
+        private int mState = Display.STATE_UNKNOWN;
 
         public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
                 SurfaceControl.PhysicalDisplayInfo phys) {
@@ -135,6 +135,7 @@
                 mInfo.width = mPhys.width;
                 mInfo.height = mPhys.height;
                 mInfo.refreshRate = mPhys.refreshRate;
+                mInfo.state = mState;
 
                 // Assume that all built-in displays that have secure output (eg. HDCP) also
                 // support compositing from gralloc protected buffers.
@@ -172,15 +173,16 @@
         }
 
         @Override
-        public void blankLocked() {
-            mBlanked = true;
-            SurfaceControl.blankDisplay(getDisplayTokenLocked());
-        }
-
-        @Override
-        public void unblankLocked() {
-            mBlanked = false;
-            SurfaceControl.unblankDisplay(getDisplayTokenLocked());
+        public void requestDisplayStateLocked(int state) {
+            if (mState != state) {
+                if (state == Display.STATE_OFF && mState != Display.STATE_OFF) {
+                    SurfaceControl.blankDisplay(getDisplayTokenLocked());
+                } else if (state != Display.STATE_OFF && mState == Display.STATE_OFF) {
+                    SurfaceControl.unblankDisplay(getDisplayTokenLocked());
+                }
+                mState = state;
+                updateDeviceInfoLocked();
+            }
         }
 
         @Override
@@ -188,7 +190,12 @@
             super.dumpLocked(pw);
             pw.println("mBuiltInDisplayId=" + mBuiltInDisplayId);
             pw.println("mPhys=" + mPhys);
-            pw.println("mBlanked=" + mBlanked);
+            pw.println("mState=" + Display.stateToString(mState));
+        }
+
+        private void updateDeviceInfoLocked() {
+            mInfo = null;
+            sendDisplayDeviceEventLocked(this, DISPLAY_DEVICE_EVENT_CHANGED);
         }
     }
 
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 7e357c0..5499af6 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -114,6 +114,7 @@
                 mInfo.copyFrom(mOverrideDisplayInfo);
                 mInfo.layerStack = mBaseDisplayInfo.layerStack;
                 mInfo.name = mBaseDisplayInfo.name;
+                mInfo.state = mBaseDisplayInfo.state;
             } else {
                 mInfo.copyFrom(mBaseDisplayInfo);
             }
@@ -212,6 +213,7 @@
             mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi;
             mBaseDisplayInfo.physicalXDpi = deviceInfo.xDpi;
             mBaseDisplayInfo.physicalYDpi = deviceInfo.yDpi;
+            mBaseDisplayInfo.state = deviceInfo.state;
             mBaseDisplayInfo.smallestNominalAppWidth = deviceInfo.width;
             mBaseDisplayInfo.smallestNominalAppHeight = deviceInfo.height;
             mBaseDisplayInfo.largestNominalAppWidth = deviceInfo.width;
diff --git a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
index 007acf7..bfd8372c 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -194,12 +194,14 @@
         private final int mDensityDpi;
         private final boolean mSecure;
 
-        private Surface mSurface;
+        private int mState;
         private SurfaceTexture mSurfaceTexture;
+        private Surface mSurface;
         private DisplayDeviceInfo mInfo;
 
         public OverlayDisplayDevice(IBinder displayToken, String name,
-                int width, int height, float refreshRate, int densityDpi, boolean secure,
+                int width, int height, float refreshRate,
+                int densityDpi, boolean secure, int state,
                 SurfaceTexture surfaceTexture) {
             super(OverlayDisplayAdapter.this, displayToken);
             mName = name;
@@ -208,6 +210,7 @@
             mRefreshRate = refreshRate;
             mDensityDpi = densityDpi;
             mSecure = secure;
+            mState = state;
             mSurfaceTexture = surfaceTexture;
         }
 
@@ -230,6 +233,11 @@
             }
         }
 
+        public void setStateLocked(int state) {
+            mState = state;
+            mInfo = null;
+        }
+
         @Override
         public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
             if (mInfo == null) {
@@ -247,6 +255,7 @@
                 }
                 mInfo.type = Display.TYPE_OVERLAY;
                 mInfo.touch = DisplayDeviceInfo.TOUCH_NONE;
+                mInfo.state = mState;
             }
             return mInfo;
         }
@@ -288,11 +297,12 @@
 
         // Called on the UI thread.
         @Override
-        public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate) {
+        public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate, int state) {
             synchronized (getSyncRoot()) {
                 IBinder displayToken = SurfaceControl.createDisplay(mName, mSecure);
                 mDevice = new OverlayDisplayDevice(displayToken, mName,
-                        mWidth, mHeight, refreshRate, mDensityDpi, mSecure, surfaceTexture);
+                        mWidth, mHeight, refreshRate, mDensityDpi, mSecure,
+                        state, surfaceTexture);
 
                 sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_ADDED);
             }
@@ -309,6 +319,17 @@
             }
         }
 
+        // Called on the UI thread.
+        @Override
+        public void onStateChanged(int state) {
+            synchronized (getSyncRoot()) {
+                if (mDevice != null) {
+                    mDevice.setStateLocked(state);
+                    sendDisplayDeviceEventLocked(mDevice, DISPLAY_DEVICE_EVENT_CHANGED);
+                }
+            }
+        }
+
         public void dumpLocked(PrintWriter pw) {
             pw.println("  " + mName + ":");
             pw.println("    mWidth=" + mWidth);
diff --git a/services/core/java/com/android/server/display/OverlayDisplayWindow.java b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
index f1dd60a..06891f3 100644
--- a/services/core/java/com/android/server/display/OverlayDisplayWindow.java
+++ b/services/core/java/com/android/server/display/OverlayDisplayWindow.java
@@ -282,6 +282,7 @@
             if (displayId == mDefaultDisplay.getDisplayId()) {
                 if (updateDefaultDisplayInfo()) {
                     relayout();
+                    mListener.onStateChanged(mDefaultDisplayInfo.state);
                 } else {
                     dismiss();
                 }
@@ -301,7 +302,8 @@
         @Override
         public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture,
                 int width, int height) {
-            mListener.onWindowCreated(surfaceTexture, mDefaultDisplayInfo.refreshRate);
+            mListener.onWindowCreated(surfaceTexture, mDefaultDisplayInfo.refreshRate,
+                    mDefaultDisplayInfo.state);
         }
 
         @Override
@@ -370,7 +372,9 @@
      * Watches for significant changes in the overlay display window lifecycle.
      */
     public interface Listener {
-        public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate);
+        public void onWindowCreated(SurfaceTexture surfaceTexture,
+                float refreshRate, int state);
         public void onWindowDestroyed();
+        public void onStateChanged(int state);
     }
 }
\ No newline at end of file
diff --git a/services/core/java/com/android/server/input/InputManagerService.java b/services/core/java/com/android/server/input/InputManagerService.java
index e49382e..a32f7c1 100644
--- a/services/core/java/com/android/server/input/InputManagerService.java
+++ b/services/core/java/com/android/server/input/InputManagerService.java
@@ -183,6 +183,7 @@
             InputChannel fromChannel, InputChannel toChannel);
     private static native void nativeSetPointerSpeed(long ptr, int speed);
     private static native void nativeSetShowTouches(long ptr, boolean enabled);
+    private static native void nativeSetInteractive(long ptr, boolean interactive);
     private static native void nativeVibrate(long ptr, int deviceId, long[] pattern,
             int repeat, int token);
     private static native void nativeCancelVibrate(long ptr, int deviceId, int token);
@@ -1360,14 +1361,13 @@
     }
 
     // Native callback.
-    private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
-        return mWindowManagerCallbacks.interceptKeyBeforeQueueing(
-                event, policyFlags, isScreenOn);
+    private int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
+        return mWindowManagerCallbacks.interceptKeyBeforeQueueing(event, policyFlags);
     }
 
     // Native callback.
-    private int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags) {
-        return mWindowManagerCallbacks.interceptMotionBeforeQueueingWhenScreenOff(
+    private int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
+        return mWindowManagerCallbacks.interceptWakeMotionBeforeQueueing(
                 whenNanos, policyFlags);
     }
 
@@ -1526,9 +1526,9 @@
         public long notifyANR(InputApplicationHandle inputApplicationHandle,
                 InputWindowHandle inputWindowHandle, String reason);
 
-        public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn);
+        public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags);
 
-        public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags);
+        public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags);
 
         public long interceptKeyBeforeDispatching(InputWindowHandle focus,
                 KeyEvent event, int policyFlags);
@@ -1696,5 +1696,10 @@
         public boolean injectInputEvent(InputEvent event, int displayId, int mode) {
             return injectInputEventInternal(event, displayId, mode);
         }
+
+        @Override
+        public void setInteractive(boolean interactive) {
+            nativeSetInteractive(mPtr, interactive);
+        }
     }
 }
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index eb7cc4c..855ae23 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -1730,7 +1730,7 @@
     private void updateScreenOn() {
         synchronized (mRulesLock) {
             try {
-                mScreenOn = mPowerManager.isScreenOn();
+                mScreenOn = mPowerManager.isInteractive();
             } catch (RemoteException e) {
                 // ignored; service lives in system_server
             }
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 19d53cb..6224ed3 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -28,6 +28,7 @@
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.hardware.input.InputManagerInternal;
 import android.media.AudioManager;
 import android.media.Ringtone;
 import android.media.RingtoneManager;
@@ -85,6 +86,7 @@
     private final ScreenOnBlocker mScreenOnBlocker;
     private final WindowManagerPolicy mPolicy;
     private final ActivityManagerInternal mActivityManagerInternal;
+    private final InputManagerInternal mInputManagerInternal;
 
     private final NotifierHandler mHandler;
     private final Intent mScreenOnIntent;
@@ -120,6 +122,7 @@
         mScreenOnBlocker = screenOnBlocker;
         mPolicy = policy;
         mActivityManagerInternal = LocalServices.getService(ActivityManagerInternal.class);
+        mInputManagerInternal = LocalServices.getService(InputManagerInternal.class);
 
         mHandler = new NotifierHandler(looper);
         mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
@@ -194,73 +197,58 @@
     }
 
     /**
-     * Called when the device is waking up from sleep and the
-     * display is about to be turned on.
+     * Notifies that the device is changing interactive state.
      */
-    public void onWakeUpStarted() {
+    public void onInteractiveStateChangeStarted(boolean interactive, int reason) {
         if (DEBUG) {
-            Slog.d(TAG, "onWakeUpStarted");
+            Slog.d(TAG, "onInteractiveChangeStarted: interactive=" + interactive
+                    + ", reason=" + reason);
         }
 
         synchronized (mLock) {
-            if (mActualPowerState != POWER_STATE_AWAKE) {
-                mActualPowerState = POWER_STATE_AWAKE;
-                mPendingWakeUpBroadcast = true;
-                if (!mScreenOnBlockerAcquired) {
-                    mScreenOnBlockerAcquired = true;
-                    mScreenOnBlocker.acquire();
+            if (interactive) {
+                // Waking up...
+                if (mActualPowerState != POWER_STATE_AWAKE) {
+                    mActualPowerState = POWER_STATE_AWAKE;
+                    mPendingWakeUpBroadcast = true;
+                    if (!mScreenOnBlockerAcquired) {
+                        mScreenOnBlockerAcquired = true;
+                        mScreenOnBlocker.acquire();
+                    }
+                    updatePendingBroadcastLocked();
                 }
-                updatePendingBroadcastLocked();
+            } else {
+                // Going to sleep...
+                mLastGoToSleepReason = reason;
             }
+            mInputManagerInternal.setInteractive(interactive);
         }
     }
 
     /**
-     * Called when the device has finished waking up from sleep
-     * and the display has been turned on.
+     * Notifies that the device has finished changing interactive state.
      */
-    public void onWakeUpFinished() {
+    public void onInteractiveStateChangeFinished(boolean interactive) {
         if (DEBUG) {
-            Slog.d(TAG, "onWakeUpFinished");
-        }
-    }
-
-    /**
-     * Called when the device is going to sleep.
-     */
-    public void onGoToSleepStarted(int reason) {
-        if (DEBUG) {
-            Slog.d(TAG, "onGoToSleepStarted");
+            Slog.d(TAG, "onInteractiveChangeFinished");
         }
 
         synchronized (mLock) {
-            mLastGoToSleepReason = reason;
-        }
-    }
-
-    /**
-     * Called when the device has finished going to sleep and the
-     * display has been turned off.
-     *
-     * This is a good time to make transitions that we don't want the user to see,
-     * such as bringing the key guard to focus.  There's no guarantee for this,
-     * however because the user could turn the device on again at any time.
-     * Some things may need to be protected by other mechanisms that defer screen on.
-     */
-    public void onGoToSleepFinished() {
-        if (DEBUG) {
-            Slog.d(TAG, "onGoToSleepFinished");
-        }
-
-        synchronized (mLock) {
-            if (mActualPowerState != POWER_STATE_ASLEEP) {
-                mActualPowerState = POWER_STATE_ASLEEP;
-                mPendingGoToSleepBroadcast = true;
-                if (mUserActivityPending) {
-                    mUserActivityPending = false;
-                    mHandler.removeMessages(MSG_USER_ACTIVITY);
+            if (!interactive) {
+                // Finished going to sleep...
+                // This is a good time to make transitions that we don't want the user to see,
+                // such as bringing the key guard to focus.  There's no guarantee for this,
+                // however because the user could turn the device on again at any time.
+                // Some things may need to be protected by other mechanisms that defer screen on.
+                if (mActualPowerState != POWER_STATE_ASLEEP) {
+                    mActualPowerState = POWER_STATE_ASLEEP;
+                    mPendingGoToSleepBroadcast = true;
+                    if (mUserActivityPending) {
+                        mUserActivityPending = false;
+                        mHandler.removeMessages(MSG_USER_ACTIVITY);
+                    }
+                    updatePendingBroadcastLocked();
                 }
-                updatePendingBroadcastLocked();
             }
         }
     }
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index 6b2ca4c..7138c3e 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -62,6 +62,7 @@
 import android.util.Log;
 import android.util.Slog;
 import android.util.TimeUtils;
+import android.view.Display;
 import android.view.WindowManagerPolicy;
 
 import java.io.FileDescriptor;
@@ -209,6 +210,10 @@
     // A bitfield that summarizes the state of all active wakelocks.
     private int mWakeLockSummary;
 
+    // True if the device is in an interactive state.
+    private boolean mInteractive;
+    private boolean mInteractiveChanging;
+
     // If true, instructs the display controller to wait for the proximity sensor to
     // go negative before turning the screen on.
     private boolean mRequestWaitForNegativeProximity;
@@ -217,11 +222,6 @@
     private long mLastWakeTime;
     private long mLastSleepTime;
 
-    // True if we need to send a wake up or go to sleep finished notification
-    // when the display is ready.
-    private boolean mSendWakeUpFinishedNotificationWhenReady;
-    private boolean mSendGoToSleepFinishedNotificationWhenReady;
-
     // Timestamp of the last call to user activity.
     private long mLastUserActivityTime;
     private long mLastUserActivityTimeNoChangeLights;
@@ -265,11 +265,11 @@
 
     // True if auto-suspend mode is enabled.
     // Refer to autosuspend.h.
-    private boolean mAutoSuspendModeEnabled;
+    private boolean mHalAutoSuspendModeEnabled;
 
     // True if interactive mode is enabled.
     // Refer to power.h.
-    private boolean mInteractiveModeEnabled;
+    private boolean mHalInteractiveModeEnabled;
 
     // True if the device is plugged into a power source.
     private boolean mIsPowered;
@@ -289,10 +289,10 @@
     private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED;
 
     // True to decouple auto-suspend mode from the display state.
-    private boolean mDecoupleAutoSuspendModeFromDisplayConfig;
+    private boolean mDecoupleHalAutoSuspendModeFromDisplayConfig;
 
     // True to decouple interactive mode from the display state.
-    private boolean mDecoupleInteractiveModeFromDisplayConfig;
+    private boolean mDecoupleHalInteractiveModeFromDisplayConfig;
 
     // True if the device should wake up when plugged or unplugged.
     private boolean mWakeUpWhenPluggedOrUnpluggedConfig;
@@ -397,7 +397,6 @@
 
     private native void nativeInit();
 
-    private static native void nativeSetPowerState(boolean screenOn, boolean screenBright);
     private static native void nativeAcquireSuspendBlocker(String name);
     private static native void nativeReleaseSuspendBlocker(String name);
     private static native void nativeSetInteractive(boolean enable);
@@ -411,13 +410,17 @@
             mDisplaySuspendBlocker = createSuspendBlockerLocked("PowerManagerService.Display");
             mDisplaySuspendBlocker.acquire();
             mHoldingDisplaySuspendBlocker = true;
+            mHalAutoSuspendModeEnabled = false;
+            mHalInteractiveModeEnabled = true;
 
             mScreenOnBlocker = new ScreenOnBlockerImpl();
             mWakefulness = WAKEFULNESS_AWAKE;
-        }
+            mInteractive = true;
 
-        nativeInit();
-        nativeSetPowerState(true, true);
+            nativeInit();
+            nativeSetAutoSuspend(false);
+            nativeSetInteractive(true);
+        }
     }
 
     @Override
@@ -445,14 +448,6 @@
 
         Watchdog.getInstance().addMonitor(this);
         Watchdog.getInstance().addThread(mHandler);
-
-        // Forcibly turn the screen on at boot so that it is in a known power state.
-        // We do this in init() rather than in the constructor because setting the
-        // screen state requires a call into surface flinger which then needs to call back
-        // into the activity manager to check permissions.  Unfortunately the
-        // activity manager is not running when the constructor is called, so we
-        // have to defer setting the screen state until this point.
-        mDisplayPowerCallbacks.unblankAllDisplays();
     }
 
     void setPolicy(WindowManagerPolicy policy) {
@@ -546,9 +541,9 @@
     private void readConfigurationLocked() {
         final Resources resources = mContext.getResources();
 
-        mDecoupleAutoSuspendModeFromDisplayConfig = resources.getBoolean(
+        mDecoupleHalAutoSuspendModeFromDisplayConfig = resources.getBoolean(
                 com.android.internal.R.bool.config_powerDecoupleAutoSuspendModeFromDisplay);
-        mDecoupleInteractiveModeFromDisplayConfig = resources.getBoolean(
+        mDecoupleHalInteractiveModeFromDisplayConfig = resources.getBoolean(
                 com.android.internal.R.bool.config_powerDecoupleInteractiveModeFromDisplay);
         mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(
                 com.android.internal.R.bool.config_unplugTurnsOnScreen);
@@ -854,11 +849,6 @@
         return false;
     }
 
-    // Called from native code.
-    private void wakeUpFromNative(long eventTime) {
-        wakeUpInternal(eventTime);
-    }
-
     private void wakeUpInternal(long eventTime) {
         synchronized (mLock) {
             if (wakeUpNoUpdateLocked(eventTime)) {
@@ -889,26 +879,16 @@
                 break;
         }
 
-        if (mWakefulness != WAKEFULNESS_DREAMING) {
-            sendPendingNotificationsLocked();
-            mNotifier.onWakeUpStarted();
-            mSendWakeUpFinishedNotificationWhenReady = true;
-        }
-
         mLastWakeTime = eventTime;
-        mWakefulness = WAKEFULNESS_AWAKE;
         mDirty |= DIRTY_WAKEFULNESS;
+        mWakefulness = WAKEFULNESS_AWAKE;
+        setInteractiveStateLocked(true, 0);
 
         userActivityNoUpdateLocked(
                 eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
         return true;
     }
 
-    // Called from native code.
-    private void goToSleepFromNative(long eventTime, int reason) {
-        goToSleepInternal(eventTime, reason);
-    }
-
     private void goToSleepInternal(long eventTime, int reason) {
         synchronized (mLock) {
             if (goToSleepNoUpdateLocked(eventTime, reason)) {
@@ -945,14 +925,11 @@
                 break;
         }
 
-        sendPendingNotificationsLocked();
-        mNotifier.onGoToSleepStarted(reason);
-        mSendGoToSleepFinishedNotificationWhenReady = true;
-
         mLastSleepTime = eventTime;
         mDirty |= DIRTY_WAKEFULNESS;
         mWakefulness = WAKEFULNESS_DOZING;
         mSandmanSummoned = true;
+        setInteractiveStateLocked(false, reason);
 
         // Report the number of wake locks that will be cleared by going to sleep.
         int numWakeLocksCleared = 0;
@@ -994,6 +971,7 @@
         mDirty |= DIRTY_WAKEFULNESS;
         mWakefulness = WAKEFULNESS_DREAMING;
         mSandmanSummoned = true;
+        setInteractiveStateLocked(true, 0);
         return true;
     }
 
@@ -1012,9 +990,27 @@
 
         mDirty |= DIRTY_WAKEFULNESS;
         mWakefulness = WAKEFULNESS_ASLEEP;
+        setInteractiveStateLocked(false, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
         return true;
     }
 
+    private void setInteractiveStateLocked(boolean interactive, int reason) {
+        if (mInteractive != interactive) {
+            finishInteractiveStateChangeLocked();
+
+            mInteractive = interactive;
+            mInteractiveChanging = true;
+            mNotifier.onInteractiveStateChangeStarted(interactive, reason);
+        }
+    }
+
+    private void finishInteractiveStateChangeLocked() {
+        if (mInteractiveChanging) {
+            mNotifier.onInteractiveStateChangeFinished(mInteractive);
+            mInteractiveChanging = false;
+        }
+    }
+
     /**
      * Updates the global power state based on dirty bits recorded in mDirty.
      *
@@ -1058,7 +1054,7 @@
 
         // Phase 3: Send notifications, if needed.
         if (mDisplayReady) {
-            sendPendingNotificationsLocked();
+            finishInteractiveStateChangeLocked();
         }
 
         // Phase 4: Update suspend blocker.
@@ -1067,17 +1063,6 @@
         updateSuspendBlockerLocked();
     }
 
-    private void sendPendingNotificationsLocked() {
-        if (mSendWakeUpFinishedNotificationWhenReady) {
-            mSendWakeUpFinishedNotificationWhenReady = false;
-            mNotifier.onWakeUpFinished();
-        }
-        if (mSendGoToSleepFinishedNotificationWhenReady) {
-            mSendGoToSleepFinishedNotificationWhenReady = false;
-            mNotifier.onGoToSleepFinished();
-        }
-    }
-
     /**
      * Updates the value of mIsPowered.
      * Sets DIRTY_IS_POWERED if a change occurred.
@@ -1197,48 +1182,45 @@
                         mWakeLockSummary |= WAKE_LOCK_CPU;
                         break;
                     case PowerManager.FULL_WAKE_LOCK:
-                        if (mWakefulness == WAKEFULNESS_AWAKE
-                                || mWakefulness == WAKEFULNESS_DREAMING) {
-                            mWakeLockSummary |= WAKE_LOCK_CPU
-                                    | WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
-                        }
-                        if (mWakefulness == WAKEFULNESS_AWAKE) {
-                            mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
-                        }
+                        mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
                         break;
                     case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
-                        if (mWakefulness == WAKEFULNESS_AWAKE
-                                || mWakefulness == WAKEFULNESS_DREAMING) {
-                            mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_BRIGHT;
-                        }
-                        if (mWakefulness == WAKEFULNESS_AWAKE) {
-                            mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
-                        }
+                        mWakeLockSummary |= WAKE_LOCK_SCREEN_BRIGHT;
                         break;
                     case PowerManager.SCREEN_DIM_WAKE_LOCK:
-                        if (mWakefulness == WAKEFULNESS_AWAKE
-                                || mWakefulness == WAKEFULNESS_DREAMING) {
-                            mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_DIM;
-                        }
-                        if (mWakefulness == WAKEFULNESS_AWAKE) {
-                            mWakeLockSummary |= WAKE_LOCK_STAY_AWAKE;
-                        }
+                        mWakeLockSummary |= WAKE_LOCK_SCREEN_DIM;
                         break;
                     case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
-                        if (mWakefulness == WAKEFULNESS_AWAKE
-                                || mWakefulness == WAKEFULNESS_DREAMING
-                                || mWakefulness == WAKEFULNESS_DOZING) {
-                            mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
-                        }
+                        mWakeLockSummary |= WAKE_LOCK_PROXIMITY_SCREEN_OFF;
                         break;
                     case PowerManager.DOZE_WAKE_LOCK:
-                        if (mWakefulness == WAKEFULNESS_DOZING) {
-                            mWakeLockSummary |= WAKE_LOCK_DOZE;
-                        }
+                        mWakeLockSummary |= WAKE_LOCK_DOZE;
                         break;
                 }
             }
 
+            // Cancel wake locks that make no sense based on the current state.
+            if (mWakefulness != WAKEFULNESS_DOZING) {
+                mWakeLockSummary &= ~WAKE_LOCK_DOZE;
+            }
+            if (mWakefulness == WAKEFULNESS_ASLEEP
+                    || (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
+                mWakeLockSummary &= ~(WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM
+                        | WAKE_LOCK_BUTTON_BRIGHT);
+                if (mWakefulness == WAKEFULNESS_ASLEEP) {
+                    mWakeLockSummary &= ~WAKE_LOCK_PROXIMITY_SCREEN_OFF;
+                }
+            }
+
+            // Infer implied wake locks where necessary based on the current state.
+            if ((mWakeLockSummary & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) != 0) {
+                if (mWakefulness == WAKEFULNESS_AWAKE) {
+                    mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_STAY_AWAKE;
+                } else if (mWakefulness == WAKEFULNESS_DREAMING) {
+                    mWakeLockSummary |= WAKE_LOCK_CPU;
+                }
+            }
+
             if (DEBUG_SPEW) {
                 Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
                         + wakefulnessToString(mWakefulness)
@@ -1256,12 +1238,14 @@
      */
     private void updateUserActivitySummaryLocked(long now, int dirty) {
         // Update the status of the user activity timeout timer.
-        if ((dirty & (DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
+        if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY
+                | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
             mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
 
             long nextTimeout = 0;
             if (mWakefulness == WAKEFULNESS_AWAKE
-                    || mWakefulness == WAKEFULNESS_DREAMING) {
+                    || mWakefulness == WAKEFULNESS_DREAMING
+                    || mWakefulness == WAKEFULNESS_DOZING) {
                 final int screenOffTimeout = getScreenOffTimeoutLocked();
                 final int screenDimDuration = getScreenDimDurationLocked(screenOffTimeout);
 
@@ -1585,8 +1569,6 @@
                 | DIRTY_SETTINGS | DIRTY_SCREEN_ON_BLOCKER_RELEASED)) != 0) {
             final int newScreenState = getDesiredScreenPowerStateLocked();
             mDisplayPowerRequest.screenState = newScreenState;
-            nativeSetPowerState(isScreenOnLocked(),
-                    newScreenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT);
 
             int screenBrightness = mScreenBrightnessSettingDefault;
             float screenAutoBrightnessAdjustment = 0.0f;
@@ -1668,7 +1650,7 @@
 
     private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks =
             new DisplayManagerInternal.DisplayPowerCallbacks() {
-        private boolean mBlanked;
+        private int mDisplayState = Display.STATE_UNKNOWN;
 
         @Override
         public void onStateChanged() {
@@ -1699,6 +1681,33 @@
         }
 
         @Override
+        public void onDisplayStateChange(int state) {
+            // This method is only needed to support legacy display blanking behavior
+            // where the display's power state is coupled to suspend or to the power HAL.
+            // The order of operations matters here.
+            synchronized (mLock) {
+                if (mDisplayState != state) {
+                    mDisplayState = state;
+                    if (state == Display.STATE_OFF) {
+                        if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
+                            setHalInteractiveModeLocked(false);
+                        }
+                        if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+                            setHalAutoSuspendModeLocked(true);
+                        }
+                    } else {
+                        if (!mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+                            setHalAutoSuspendModeLocked(false);
+                        }
+                        if (!mDecoupleHalInteractiveModeFromDisplayConfig) {
+                            setHalInteractiveModeLocked(true);
+                        }
+                    }
+                }
+            }
+        }
+
+        @Override
         public void acquireSuspendBlocker() {
             mDisplaySuspendBlocker.acquire();
         }
@@ -1709,37 +1718,9 @@
         }
 
         @Override
-        public void blankAllDisplays() {
-            synchronized (this) {
-                mBlanked = true;
-                mDisplayManagerInternal.blankAllDisplaysFromPowerManager();
-                if (!mDecoupleInteractiveModeFromDisplayConfig) {
-                    setInteractiveModeLocked(false);
-                }
-                if (!mDecoupleAutoSuspendModeFromDisplayConfig) {
-                    setAutoSuspendModeLocked(true);
-                }
-            }
-        }
-
-        @Override
-        public void unblankAllDisplays() {
-            synchronized (this) {
-                if (!mDecoupleAutoSuspendModeFromDisplayConfig) {
-                    setAutoSuspendModeLocked(false);
-                }
-                if (!mDecoupleInteractiveModeFromDisplayConfig) {
-                    setInteractiveModeLocked(true);
-                }
-                mDisplayManagerInternal.unblankAllDisplaysFromPowerManager();
-                mBlanked = false;
-            }
-        }
-
-        @Override
         public String toString() {
             synchronized (this) {
-                return "blanked=" + mBlanked;
+                return "state=" + Display.stateToString(mDisplayState);
             }
         }
     };
@@ -1760,11 +1741,11 @@
 
         // Disable auto-suspend if needed.
         if (!autoSuspend) {
-            if (mDecoupleAutoSuspendModeFromDisplayConfig) {
-                setAutoSuspendModeLocked(false);
+            if (mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+                setHalAutoSuspendModeLocked(false);
             }
-            if (mDecoupleInteractiveModeFromDisplayConfig) {
-                setInteractiveModeLocked(true);
+            if (mDecoupleHalInteractiveModeFromDisplayConfig) {
+                setHalInteractiveModeLocked(true);
             }
         }
 
@@ -1790,11 +1771,11 @@
 
         // Enable auto-suspend if needed.
         if (autoSuspend) {
-            if (mDecoupleInteractiveModeFromDisplayConfig) {
-                setInteractiveModeLocked(false);
+            if (mDecoupleHalInteractiveModeFromDisplayConfig) {
+                setHalInteractiveModeLocked(false);
             }
-            if (mDecoupleAutoSuspendModeFromDisplayConfig) {
-                setAutoSuspendModeLocked(true);
+            if (mDecoupleHalAutoSuspendModeFromDisplayConfig) {
+                setHalAutoSuspendModeLocked(true);
             }
         }
     }
@@ -1821,42 +1802,32 @@
         return false;
     }
 
-    private void setAutoSuspendModeLocked(boolean enable) {
-        if (enable != mAutoSuspendModeEnabled) {
+    private void setHalAutoSuspendModeLocked(boolean enable) {
+        if (enable != mHalAutoSuspendModeEnabled) {
             if (DEBUG) {
-                Slog.d(TAG, "Setting auto-suspend mode to " + enable);
+                Slog.d(TAG, "Setting HAL auto-suspend mode to " + enable);
             }
-            mAutoSuspendModeEnabled = enable;
+            mHalAutoSuspendModeEnabled = enable;
             nativeSetAutoSuspend(enable);
         }
     }
 
-    private void setInteractiveModeLocked(boolean enable) {
-        if (enable != mInteractiveModeEnabled) {
+    private void setHalInteractiveModeLocked(boolean enable) {
+        if (enable != mHalInteractiveModeEnabled) {
             if (DEBUG) {
-                Slog.d(TAG, "Setting interactive mode to " + enable);
+                Slog.d(TAG, "Setting HAL interactive mode to " + enable);
             }
-            mInteractiveModeEnabled = enable;
+            mHalInteractiveModeEnabled = enable;
             nativeSetInteractive(enable);
         }
     }
 
-    private boolean isScreenOnInternal() {
+    private boolean isInteractiveInternal() {
         synchronized (mLock) {
-            // XXX This is a temporary hack to let certain parts of the system pretend the
-            // screen is still on even when dozing and we would normally want to report
-            // screen off.  Will be removed when the window manager is modified to use
-            // the true blanking state of the display.
-            return isScreenOnLocked()
-                    || mWakefulness == WAKEFULNESS_DOZING;
+            return mInteractive;
         }
     }
 
-    private boolean isScreenOnLocked() {
-        return mWakefulness == WAKEFULNESS_AWAKE
-                || mWakefulness == WAKEFULNESS_DREAMING;
-    }
-
     private void handleBatteryStateChangedLocked() {
         mDirty |= DIRTY_BATTERY_STATE;
         updatePowerStateLocked();
@@ -2061,6 +2032,7 @@
             pw.println("Power Manager State:");
             pw.println("  mDirty=0x" + Integer.toHexString(mDirty));
             pw.println("  mWakefulness=" + wakefulnessToString(mWakefulness));
+            pw.println("  mInteractive=" + mInteractive);
             pw.println("  mIsPowered=" + mIsPowered);
             pw.println("  mPlugType=" + mPlugType);
             pw.println("  mBatteryLevel=" + mBatteryLevel);
@@ -2070,8 +2042,8 @@
             pw.println("  mProximityPositive=" + mProximityPositive);
             pw.println("  mBootCompleted=" + mBootCompleted);
             pw.println("  mSystemReady=" + mSystemReady);
-            pw.println("  mAutoSuspendModeEnabled=" + mAutoSuspendModeEnabled);
-            pw.println("  mInteactiveModeEnabled=" + mInteractiveModeEnabled);
+            pw.println("  mHalAutoSuspendModeEnabled=" + mHalAutoSuspendModeEnabled);
+            pw.println("  mHalInteractiveModeEnabled=" + mHalInteractiveModeEnabled);
             pw.println("  mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
             pw.println("  mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary));
             pw.println("  mRequestWaitForNegativeProximity=" + mRequestWaitForNegativeProximity);
@@ -2079,10 +2051,6 @@
             pw.println("  mSandmanSummoned=" + mSandmanSummoned);
             pw.println("  mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime));
             pw.println("  mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime));
-            pw.println("  mSendWakeUpFinishedNotificationWhenReady="
-                    + mSendWakeUpFinishedNotificationWhenReady);
-            pw.println("  mSendGoToSleepFinishedNotificationWhenReady="
-                    + mSendGoToSleepFinishedNotificationWhenReady);
             pw.println("  mLastUserActivityTime=" + TimeUtils.formatUptime(mLastUserActivityTime));
             pw.println("  mLastUserActivityTimeNoChangeLights="
                     + TimeUtils.formatUptime(mLastUserActivityTimeNoChangeLights));
@@ -2092,10 +2060,10 @@
 
             pw.println();
             pw.println("Settings and Configuration:");
-            pw.println("  mDecoupleAutoSuspendModeFromDisplayConfig="
-                    + mDecoupleAutoSuspendModeFromDisplayConfig);
-            pw.println("  mDecoupleInteractiveModeFromDisplayConfig="
-                    + mDecoupleInteractiveModeFromDisplayConfig);
+            pw.println("  mDecoupleHalAutoSuspendModeFromDisplayConfig="
+                    + mDecoupleHalAutoSuspendModeFromDisplayConfig);
+            pw.println("  mDecoupleHalInteractiveModeFromDisplayConfig="
+                    + mDecoupleHalInteractiveModeFromDisplayConfig);
             pw.println("  mWakeUpWhenPluggedOrUnpluggedConfig="
                     + mWakeUpWhenPluggedOrUnpluggedConfig);
             pw.println("  mSuspendWhenScreenOffDueToProximityConfig="
@@ -2684,10 +2652,10 @@
         }
 
         @Override // Binder call
-        public boolean isScreenOn() {
+        public boolean isInteractive() {
             final long ident = Binder.clearCallingIdentity();
             try {
-                return isScreenOnInternal();
+                return isInteractiveInternal();
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 4aae5c1..b27c8d6 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -355,17 +355,16 @@
     /* Provides an opportunity for the window manager policy to intercept early key
      * processing as soon as the key has been read from the device. */
     @Override
-    public int interceptKeyBeforeQueueing(
-            KeyEvent event, int policyFlags, boolean isScreenOn) {
-        return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags, isScreenOn);
+    public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags) {
+        return mService.mPolicy.interceptKeyBeforeQueueing(event, policyFlags);
     }
 
     /* Provides an opportunity for the window manager policy to intercept early
      * motion event processing when the screen is off since these events are normally
      * dropped. */
     @Override
-    public int interceptMotionBeforeQueueingWhenScreenOff(long whenNanos, int policyFlags) {
-        return mService.mPolicy.interceptMotionBeforeQueueingWhenScreenOff(whenNanos, policyFlags);
+    public int interceptWakeMotionBeforeQueueing(long whenNanos, int policyFlags) {
+        return mService.mPolicy.interceptWakeMotionBeforeQueueing(whenNanos, policyFlags);
     }
 
     /* Provides an opportunity for the window manager policy to process a key before