OSDN Git Service

Coordinate screen on with the window manager.
authorJeff Brown <jeffbrown@google.com>
Thu, 4 Oct 2012 20:16:19 +0000 (13:16 -0700)
committerJeff Brown <jeffbrown@google.com>
Fri, 5 Oct 2012 21:39:23 +0000 (14:39 -0700)
Bug: 7267457
Change-Id: Ic2c322253639e1f0b2e4e72a7b145025d0240f93

core/java/android/view/IWindowManager.aidl
core/java/android/view/WindowManagerPolicy.java
policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
services/java/com/android/server/power/DisplayPowerController.java
services/java/com/android/server/power/DisplayPowerRequest.java
services/java/com/android/server/power/Notifier.java
services/java/com/android/server/power/PowerManagerService.java
services/java/com/android/server/power/ScreenOnBlocker.java [new file with mode: 0644]
services/java/com/android/server/wm/WindowManagerService.java
tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowManager.java

index f7ba38c..e3250f9 100644 (file)
@@ -201,8 +201,9 @@ interface IWindowManager
 
     /**
      * Block until the given window has been drawn to the screen.
+     * Returns true if really waiting, false if the window does not exist.
      */
-    void waitForWindowDrawn(IBinder token, in IRemoteCallback callback);
+    boolean waitForWindowDrawn(IBinder token, in IRemoteCallback callback);
 
     /**
      * Device has a software navigation bar (separate from the status bar).
index 04b5e11..d25f4cd 100644 (file)
@@ -1058,18 +1058,13 @@ public interface WindowManagerPolicy {
      * Called when we have started keeping the screen on because a window
      * requesting this has become visible.
      */
-    public void screenOnStartedLw();
+    public void keepScreenOnStartedLw();
 
     /**
      * Called when we have stopped keeping the screen on because the last window
      * requesting this is no longer visible.
      */
-    public void screenOnStoppedLw();
-
-    /**
-     * Return false to disable key repeat events from being generated.
-     */
-    public boolean allowKeyRepeat();
+    public void keepScreenOnStoppedLw();
 
     /**
      * Inform the policy that the user has chosen a preferred orientation ("rotation lock"). 
index ed9c6a3..60c6d06 100755 (executable)
@@ -3580,7 +3580,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
         }
     };
 
-    /** {@inheritDoc} */
+    @Override
     public void screenTurnedOff(int why) {
         EventLog.writeEvent(70000, 0);
         synchronized (mLock) {
@@ -3596,7 +3596,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
         }
     }
 
-    /** {@inheritDoc} */
+    @Override
     public void screenTurningOn(final ScreenOnListener screenOnListener) {
         EventLog.writeEvent(70000, 1);
         if (false) {
@@ -3604,64 +3604,83 @@ public class PhoneWindowManager implements WindowManagerPolicy {
             here.fillInStackTrace();
             Slog.i(TAG, "Screen turning on...", here);
         }
-        if (screenOnListener != null) {
-            if (mKeyguardMediator != null) {
-                try {
-                    mWindowManager.setEventDispatching(true);
-                } catch (RemoteException unhandled) {
-                }
+
+        synchronized (mLock) {
+            mScreenOnEarly = true;
+            updateOrientationListenerLp();
+            updateLockScreenTimeout();
+        }
+
+        try {
+            mWindowManager.setEventDispatching(true);
+        } catch (RemoteException unhandled) {
+        }
+
+        waitForKeyguard(screenOnListener);
+    }
+
+    private void waitForKeyguard(final ScreenOnListener screenOnListener) {
+        if (mKeyguardMediator != null) {
+            if (screenOnListener != null) {
                 mKeyguardMediator.onScreenTurnedOn(new KeyguardViewManager.ShowListener() {
-                    @Override public void onShown(IBinder windowToken) {
-                        if (windowToken != null) {
-                            try {
-                                mWindowManager.waitForWindowDrawn(windowToken,
-                                        new IRemoteCallback.Stub() {
-                                    @Override public void sendResult(Bundle data) {
-                                        Slog.i(TAG, "Lock screen displayed!");
-                                        screenOnListener.onScreenOn();
-                                        synchronized (mLock) {
-                                            mScreenOnFully = true;
-                                        }
-                                    }
-                                });
-                            } catch (RemoteException e) {
-                            }
-                        } else {
-                            Slog.i(TAG, "No lock screen!");
-                            screenOnListener.onScreenOn();
-                            synchronized (mLock) {
-                                mScreenOnFully = true;
-                            }
-                        }
+                    @Override
+                    public void onShown(IBinder windowToken) {
+                        waitForKeyguardWindowDrawn(windowToken, screenOnListener);
                     }
                 });
-            }
-        } else {
-            if (mKeyguardMediator != null) {
-                // Must set mScreenOn = true.
+                return;
+            } else {
                 mKeyguardMediator.onScreenTurnedOn(null);
             }
-            synchronized (mLock) {
-                mScreenOnFully = true;
+        } else {
+            Slog.i(TAG, "No keyguard mediator!");
+        }
+        finishScreenTurningOn(screenOnListener);
+    }
+
+    private void waitForKeyguardWindowDrawn(IBinder windowToken,
+            final ScreenOnListener screenOnListener) {
+        if (windowToken != null) {
+            try {
+                if (mWindowManager.waitForWindowDrawn(
+                        windowToken, new IRemoteCallback.Stub() {
+                    @Override
+                    public void sendResult(Bundle data) {
+                        Slog.i(TAG, "Lock screen displayed!");
+                        finishScreenTurningOn(screenOnListener);
+                    }
+                })) {
+                    return;
+                }
+            } catch (RemoteException ex) {
+                // Can't happen in system process.
             }
         }
+
+        Slog.i(TAG, "No lock screen!");
+        finishScreenTurningOn(screenOnListener);
+    }
+
+    private void finishScreenTurningOn(ScreenOnListener screenOnListener) {
         synchronized (mLock) {
-            mScreenOnEarly = true;
-            updateOrientationListenerLp();
-            updateLockScreenTimeout();
+            mScreenOnFully = true;
+        }
+
+        if (screenOnListener != null) {
+            screenOnListener.onScreenOn();
         }
     }
 
-    /** {@inheritDoc} */
+    @Override
     public boolean isScreenOnEarly() {
         return mScreenOnEarly;
     }
-    
-    /** {@inheritDoc} */
+
+    @Override
     public boolean isScreenOnFully() {
         return mScreenOnFully;
     }
-    
+
     /** {@inheritDoc} */
     public void enableKeyguard(boolean enabled) {
         if (mKeyguardMediator != null) {
@@ -4236,22 +4255,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
         }
         return true;
     }
-    
-    public void screenOnStartedLw() {
-    }
 
-    public void screenOnStoppedLw() {
-        if (mPowerManager.isScreenOn()) {
-            if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) {
-                long curTime = SystemClock.uptimeMillis();
-                mPowerManager.userActivity(curTime, false);
-            }
-        }
+    @Override
+    public void keepScreenOnStartedLw() {
     }
 
-    public boolean allowKeyRepeat() {
-        // disable key repeat when screen is off
-        return mScreenOnEarly;
+    @Override
+    public void keepScreenOnStoppedLw() {
+        if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) {
+            long curTime = SystemClock.uptimeMillis();
+            mPowerManager.userActivity(curTime, false);
+        }
     }
 
     private int updateSystemUiVisibilityLw() {
index b9f9df7..23df701 100644 (file)
@@ -531,6 +531,7 @@ final class DisplayPowerController {
         final boolean mustNotify;
         boolean mustInitialize = false;
         boolean updateAutoBrightness = mTwilightChanged;
+        boolean screenOnWasBlocked = false;
         mTwilightChanged = false;
 
         synchronized (mLock) {
@@ -588,7 +589,6 @@ final class DisplayPowerController {
             if (mScreenOffBecauseOfProximity
                     && mProximity != PROXIMITY_POSITIVE) {
                 mScreenOffBecauseOfProximity = false;
-                setScreenOn(true);
                 sendOnProximityNegative();
             }
         } else {
@@ -639,20 +639,43 @@ final class DisplayPowerController {
                 // It is relatively short but if we cancel it and switch to the
                 // on animation immediately then the results are pretty ugly.
                 if (!mElectronBeamOffAnimator.isStarted()) {
-                    setScreenOn(true);
-                    if (USE_ELECTRON_BEAM_ON_ANIMATION) {
-                        if (!mElectronBeamOnAnimator.isStarted()) {
-                            if (mPowerState.getElectronBeamLevel() == 1.0f) {
-                                mPowerState.dismissElectronBeam();
-                            } else if (mPowerState.prepareElectronBeam(true)) {
-                                mElectronBeamOnAnimator.start();
-                            } else {
-                                mElectronBeamOnAnimator.end();
-                            }
+                    if (mPowerRequest.blockScreenOn && !mPowerState.isScreenOn()) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "Blocked screen on while screen currently off.");
                         }
+                        screenOnWasBlocked = true;
                     } else {
-                        mPowerState.setElectronBeamLevel(1.0f);
-                        mPowerState.dismissElectronBeam();
+                        setScreenOn(true);
+                        if (USE_ELECTRON_BEAM_ON_ANIMATION) {
+                            if (!mElectronBeamOnAnimator.isStarted()) {
+                                if (mPowerState.getElectronBeamLevel() == 1.0f) {
+                                    mPowerState.dismissElectronBeam();
+                                } else if (mPowerState.prepareElectronBeam(true)) {
+                                    mElectronBeamOnAnimator.start();
+                                } else {
+                                    mElectronBeamOnAnimator.end();
+                                }
+                            }
+                        } else {
+                            mPowerState.setElectronBeamLevel(1.0f);
+                            mPowerState.dismissElectronBeam();
+                        }
+                    }
+                } else {
+                    // FIXME: If the electron beam off animation is playing then we have a bit
+                    // of a problem.  The window manager policy would only have requested
+                    // to block screen on if it was about to start preparing the keyguard.
+                    // It's already too late to do anything about that.  Ideally we would
+                    // let the animation play out first but that would require making
+                    // some pretty deep changes to the power manager and we don't have
+                    // time just now.  For now, short-circuit the animation and get ready.
+                    if (mPowerRequest.blockScreenOn) {
+                        if (DEBUG) {
+                            Slog.d(TAG, "Blocked screen on while screen off animation running.");
+                        }
+                        screenOnWasBlocked = true;
+                        setScreenOn(false);
+                        mElectronBeamOffAnimator.end();
                     }
                 }
             } else {
@@ -677,12 +700,17 @@ final class DisplayPowerController {
         // We mostly care about the screen state here, ignoring brightness changes
         // which will be handled asynchronously.
         if (mustNotify
+                && !screenOnWasBlocked
                 && !mElectronBeamOnAnimator.isStarted()
                 && !mElectronBeamOffAnimator.isStarted()
                 && mPowerState.waitUntilClean(mCleanListener)) {
             synchronized (mLock) {
                 if (!mPendingRequestChangedLocked) {
                     mDisplayReadyLocked = true;
+
+                    if (DEBUG) {
+                        Slog.d(TAG, "Display ready!");
+                    }
                 }
             }
             sendOnStateChanged();
index 2d74292..5f94414 100644 (file)
@@ -52,12 +52,20 @@ final class DisplayPowerRequest {
     // If true, enables automatic brightness control.
     public boolean useAutoBrightness;
 
+    // If true, prevents the screen from turning on if it is currently off.
+    // The display does not enter a "ready" state if this flag is true and the screen
+    // is off and is being prevented from turning on.  The window manager policy blocks
+    // screen on while it prepares the keyguard to prevent the user from seeing
+    // intermediate updates.
+    public boolean blockScreenOn;
+
     public DisplayPowerRequest() {
         screenState = SCREEN_STATE_BRIGHT;
         useProximitySensor = false;
         screenBrightness = PowerManager.BRIGHTNESS_ON;
         screenAutoBrightnessAdjustment = 0.0f;
         useAutoBrightness = false;
+        blockScreenOn = false;
     }
 
     public DisplayPowerRequest(DisplayPowerRequest other) {
@@ -70,6 +78,7 @@ final class DisplayPowerRequest {
         screenBrightness = other.screenBrightness;
         screenAutoBrightnessAdjustment = other.screenAutoBrightnessAdjustment;
         useAutoBrightness = other.useAutoBrightness;
+        blockScreenOn = other.blockScreenOn;
     }
 
     @Override
@@ -84,7 +93,8 @@ final class DisplayPowerRequest {
                 && useProximitySensor == other.useProximitySensor
                 && screenBrightness == other.screenBrightness
                 && screenAutoBrightnessAdjustment == other.screenAutoBrightnessAdjustment
-                && useAutoBrightness == other.useAutoBrightness;
+                && useAutoBrightness == other.useAutoBrightness
+                && blockScreenOn == other.blockScreenOn;
     }
 
     @Override
@@ -98,6 +108,7 @@ final class DisplayPowerRequest {
                 + ", useProximitySensor=" + useProximitySensor
                 + ", screenBrightness=" + screenBrightness
                 + ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment
-                + ", useAutoBrightness=" + useAutoBrightness;
+                + ", useAutoBrightness=" + useAutoBrightness
+                + ", blockScreenOn=" + blockScreenOn;
     }
 }
index 3042124..5e05693 100644 (file)
@@ -35,7 +35,6 @@ import android.os.WorkSource;
 import android.util.EventLog;
 import android.util.Slog;
 import android.view.WindowManagerPolicy;
-import android.view.WindowManagerPolicy.ScreenOnListener;
 
 /**
  * Sends broadcasts about important power state changes.
@@ -71,8 +70,8 @@ final class Notifier {
     private final Context mContext;
     private final IBatteryStats mBatteryStats;
     private final SuspendBlocker mSuspendBlocker;
+    private final ScreenOnBlocker mScreenOnBlocker;
     private final WindowManagerPolicy mPolicy;
-    private final ScreenOnListener mScreenOnListener;
 
     private final NotifierHandler mHandler;
     private final Intent mScreenOnIntent;
@@ -95,14 +94,17 @@ final class Notifier {
     // True if a user activity message should be sent.
     private boolean mUserActivityPending;
 
+    // True if the screen on blocker has been acquired.
+    private boolean mScreenOnBlockerAcquired;
+
     public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
-            SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
-            ScreenOnListener screenOnListener) {
+            SuspendBlocker suspendBlocker, ScreenOnBlocker screenOnBlocker,
+            WindowManagerPolicy policy) {
         mContext = context;
         mBatteryStats = batteryStats;
         mSuspendBlocker = suspendBlocker;
+        mScreenOnBlocker = screenOnBlocker;
         mPolicy = policy;
-        mScreenOnListener = screenOnListener;
 
         mHandler = new NotifierHandler(looper);
         mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
@@ -227,6 +229,10 @@ final class Notifier {
             if (mActualPowerState != POWER_STATE_AWAKE) {
                 mActualPowerState = POWER_STATE_AWAKE;
                 mPendingWakeUpBroadcast = true;
+                if (!mScreenOnBlockerAcquired) {
+                    mScreenOnBlockerAcquired = true;
+                    mScreenOnBlocker.acquire();
+                }
                 updatePendingBroadcastLocked();
             }
         }
@@ -387,6 +393,7 @@ final class Notifier {
         EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
 
         mPolicy.screenTurningOn(mScreenOnListener);
+
         try {
             ActivityManagerNative.getDefault().wakingUp();
         } catch (RemoteException e) {
@@ -402,6 +409,19 @@ final class Notifier {
         }
     }
 
+    private final WindowManagerPolicy.ScreenOnListener mScreenOnListener =
+            new WindowManagerPolicy.ScreenOnListener() {
+        @Override
+        public void onScreenOn() {
+            synchronized (mLock) {
+                if (mScreenOnBlockerAcquired && !mPendingWakeUpBroadcast) {
+                    mScreenOnBlockerAcquired = false;
+                    mScreenOnBlocker.release();
+                }
+            }
+        }
+    };
+
     private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
index ae7b2d1..f584302 100644 (file)
@@ -79,6 +79,8 @@ public final class PowerManagerService extends IPowerManager.Stub
     private static final int MSG_USER_ACTIVITY_TIMEOUT = 1;
     // Message: Sent when the device enters or exits a napping or dreaming state.
     private static final int MSG_SANDMAN = 2;
+    // Message: Sent when the screen on blocker is released.
+    private static final int MSG_SCREEN_ON_BLOCKER_RELEASED = 3;
 
     // Dirty bit: mWakeLocks changed
     private static final int DIRTY_WAKE_LOCKS = 1 << 0;
@@ -100,6 +102,8 @@ public final class PowerManagerService extends IPowerManager.Stub
     private static final int DIRTY_BATTERY_STATE = 1 << 8;
     // Dirty bit: proximity state changed
     private static final int DIRTY_PROXIMITY_POSITIVE = 1 << 9;
+    // Dirty bit: screen on blocker state became held or unheld
+    private static final int DIRTY_SCREEN_ON_BLOCKER_RELEASED = 1 << 10;
 
     // Wakefulness: The device is asleep and can only be awoken by a call to wakeUp().
     // The screen should be off or in the process of being turned off by the display controller.
@@ -222,6 +226,10 @@ public final class PowerManagerService extends IPowerManager.Stub
     // The suspend blocker used to keep the CPU alive when wake locks have been acquired.
     private final SuspendBlocker mWakeLockSuspendBlocker;
 
+    // The screen on blocker used to keep the screen from turning on while the lock
+    // screen is coming up.
+    private final ScreenOnBlockerImpl mScreenOnBlocker;
+
     // True if systemReady() has been called.
     private boolean mSystemReady;
 
@@ -318,6 +326,7 @@ public final class PowerManagerService extends IPowerManager.Stub
         synchronized (mLock) {
             mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService");
             mWakeLockSuspendBlocker.acquire();
+            mScreenOnBlocker = new ScreenOnBlockerImpl();
             mHoldingWakeLockSuspendBlocker = true;
             mWakefulness = WAKEFULNESS_AWAKE;
         }
@@ -368,9 +377,14 @@ public final class PowerManagerService extends IPowerManager.Stub
             mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
             mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
 
-            mNotifier = new Notifier(mHandler.getLooper(), mContext, mBatteryStats,
+            // The notifier runs on the system server's main looper so as not to interfere
+            // with the animations and other critical functions of the power manager.
+            mNotifier = new Notifier(Looper.getMainLooper(), mContext, mBatteryStats,
                     createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
-                    mPolicy, mScreenOnListener);
+                    mScreenOnBlocker, mPolicy);
+
+            // The display power controller runs on the power manager service's
+            // own handler thread.
             mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
                     mContext, mNotifier, mLightsService, twilight,
                     createSuspendBlockerLocked("PowerManagerService.Display"),
@@ -1433,6 +1447,13 @@ public final class PowerManagerService extends IPowerManager.Stub
         }
     }
 
+    private void handleScreenOnBlockerReleased() {
+        synchronized (mLock) {
+            mDirty |= DIRTY_SCREEN_ON_BLOCKER_RELEASED;
+            updatePowerStateLocked();
+        }
+    }
+
     /**
      * Updates the display power state asynchronously.
      * When the update is finished, mDisplayReady will be set to true.  The display
@@ -1444,8 +1465,8 @@ public final class PowerManagerService extends IPowerManager.Stub
     private void updateDisplayPowerStateLocked(int dirty) {
         if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
                 | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
-                | DIRTY_SETTINGS)) != 0) {
-            int newScreenState = getDesiredScreenPowerState();
+                | DIRTY_SETTINGS | DIRTY_SCREEN_ON_BLOCKER_RELEASED)) != 0) {
+            int newScreenState = getDesiredScreenPowerStateLocked();
             if (newScreenState != mDisplayPowerRequest.screenState) {
                 if (newScreenState == DisplayPowerRequest.SCREEN_STATE_OFF
                         && mDisplayPowerRequest.screenState
@@ -1493,12 +1514,14 @@ public final class PowerManagerService extends IPowerManager.Stub
 
             mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
 
+            mDisplayPowerRequest.blockScreenOn = mScreenOnBlocker.isHeld();
+
             mDisplayReady = mDisplayPowerController.requestPowerState(mDisplayPowerRequest,
                     mRequestWaitForNegativeProximity);
             mRequestWaitForNegativeProximity = false;
 
             if (DEBUG_SPEW) {
-                Slog.d(TAG, "updateScreenStateLocked: displayReady=" + mDisplayReady
+                Slog.d(TAG, "updateScreenStateLocked: mDisplayReady=" + mDisplayReady
                         + ", newScreenState=" + newScreenState
                         + ", mWakefulness=" + mWakefulness
                         + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
@@ -1517,7 +1540,7 @@ public final class PowerManagerService extends IPowerManager.Stub
         return value >= -1.0f && value <= 1.0f;
     }
 
-    private int getDesiredScreenPowerState() {
+    private int getDesiredScreenPowerStateLocked() {
         if (mWakefulness == WAKEFULNESS_ASLEEP) {
             return DisplayPowerRequest.SCREEN_STATE_OFF;
         }
@@ -2070,6 +2093,9 @@ public final class PowerManagerService extends IPowerManager.Stub
                 pw.println("  " + sb);
             }
 
+            pw.println();
+            pw.println("Screen On Blocker: " + mScreenOnBlocker);
+
             dpc = mDisplayPowerController;
         }
 
@@ -2152,13 +2178,6 @@ public final class PowerManagerService extends IPowerManager.Stub
         }
     }
 
-    private final WindowManagerPolicy.ScreenOnListener mScreenOnListener =
-            new WindowManagerPolicy.ScreenOnListener() {
-        @Override
-        public void onScreenOn() {
-        }
-    };
-
     /**
      * Handler for asynchronous operations performed by the power manager.
      */
@@ -2176,6 +2195,9 @@ public final class PowerManagerService extends IPowerManager.Stub
                 case MSG_SANDMAN:
                     handleSandman();
                     break;
+                case MSG_SCREEN_ON_BLOCKER_RELEASED:
+                    handleScreenOnBlockerReleased();
+                    break;
             }
         }
     }
@@ -2321,4 +2343,49 @@ public final class PowerManagerService extends IPowerManager.Stub
             }
         }
     }
+
+    private final class ScreenOnBlockerImpl implements ScreenOnBlocker {
+        private int mNestCount;
+
+        public boolean isHeld() {
+            synchronized (this) {
+                return mNestCount != 0;
+            }
+        }
+
+        @Override
+        public void acquire() {
+            synchronized (this) {
+                mNestCount += 1;
+                if (DEBUG) {
+                    Slog.d(TAG, "Screen on blocked: mNestCount=" + mNestCount);
+                }
+            }
+        }
+
+        @Override
+        public void release() {
+            synchronized (this) {
+                mNestCount -= 1;
+                if (mNestCount < 0) {
+                    Log.wtf(TAG, "Screen on blocker was released without being acquired!",
+                            new Throwable());
+                    mNestCount = 0;
+                }
+                if (mNestCount == 0) {
+                    mHandler.sendEmptyMessage(MSG_SCREEN_ON_BLOCKER_RELEASED);
+                }
+                if (DEBUG) {
+                    Slog.d(TAG, "Screen on unblocked: mNestCount=" + mNestCount);
+                }
+            }
+        }
+
+        @Override
+        public String toString() {
+            synchronized (this) {
+                return "held=" + (mNestCount != 0) + ", mNestCount=" + mNestCount;
+            }
+        }
+    };
 }
diff --git a/services/java/com/android/server/power/ScreenOnBlocker.java b/services/java/com/android/server/power/ScreenOnBlocker.java
new file mode 100644 (file)
index 0000000..2bf0bcf
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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.power;
+
+/**
+ * Low-level screen on blocker mechanism which is used to keep the screen off
+ * until the window manager is ready to show new content.
+ */
+interface ScreenOnBlocker {
+    /**
+     * Acquires the screen on blocker.
+     * Prevents the screen from turning on.
+     *
+     * Calls to acquire() nest and must be matched by the same number
+     * of calls to release().
+     */
+    void acquire();
+
+    /**
+     * Releases the screen on blocker.
+     * Allows the screen to turn on.
+     *
+     * It is an error to call release() if the screen on blocker has not been acquired.
+     * The system may crash.
+     */
+    void release();
+}
index 8cc3d61..8f5103c 100755 (executable)
@@ -9450,18 +9450,22 @@ public class WindowManagerService extends IWindowManager.Stub
         }
     }
 
-    public void waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
-        synchronized (mWindowMap) {
-            WindowState win = windowForClientLocked(null, token, true);
-            if (win != null) {
-                Pair<WindowState, IRemoteCallback> pair =
-                        new Pair<WindowState, IRemoteCallback>(win, callback);
-                Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
-                mH.sendMessageDelayed(m, 2000);
-                mWaitingForDrawn.add(pair);
-                checkDrawnWindowsLocked();
+    public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
+        if (token != null && callback != null) {
+            synchronized (mWindowMap) {
+                WindowState win = windowForClientLocked(null, token, true);
+                if (win != null) {
+                    Pair<WindowState, IRemoteCallback> pair =
+                            new Pair<WindowState, IRemoteCallback>(win, callback);
+                    Message m = mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, pair);
+                    mH.sendMessageDelayed(m, 2000);
+                    mWaitingForDrawn.add(pair);
+                    checkDrawnWindowsLocked();
+                    return true;
+                }
             }
         }
+        return false;
     }
 
     void setHoldScreenLocked(final Session newHoldScreen) {
@@ -9475,10 +9479,10 @@ public class WindowManagerService extends IWindowManager.Stub
         final boolean state = mHoldingScreenWakeLock.isHeld();
         if (hold != state) {
             if (hold) {
-                mPolicy.screenOnStartedLw();
                 mHoldingScreenWakeLock.acquire();
+                mPolicy.keepScreenOnStartedLw();
             } else {
-                mPolicy.screenOnStoppedLw();
+                mPolicy.keepScreenOnStoppedLw();
                 mHoldingScreenWakeLock.release();
             }
         }
index dbd52a0..9ddaf63 100644 (file)
@@ -414,8 +414,8 @@ public class BridgeWindowManager implements IWindowManager {
     }
 
     @Override
-    public void waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
-        // TODO Auto-generated method stub
+    public boolean waitForWindowDrawn(IBinder token, IRemoteCallback callback) {
+        return false;
     }
 
     @Override