diff options
author | Jeff Brown <jeffbrown@google.com> | 2012-10-07 14:54:17 -0700 |
---|---|---|
committer | Jeff Brown <jeffbrown@google.com> | 2012-10-07 14:54:17 -0700 |
commit | 8b9cf1c8000eb581457713a5c0ce41c59f90c353 (patch) | |
tree | 3ff369a13efd5932b993bbc76098362e84e761cb /services/java/com/android/server/power/DisplayPowerController.java | |
parent | 138f272bfcd45f233abfd94faf4aabaa5d01b90b (diff) |
Reduce screen on latency, eliminate flashes.
Always use the ElectronBeam now, even when we are only animating
the backlight so that we will have a black surface remaining
on the screen after the screen turns off.
When turning on the screen, keep the black surface showing until
we unblock screen on then dismiss it as usual.
This change eliminates the flashing of old display content when
the screen is turned on. It also helps to conceal some of the
latency of turning the screen on. We always turn the screen on
immediately (even when screen on has nominally been blocked) and
rely on the black surface to hide the screen contents until the
last moment. Dismissing the black surface is practically
instantaneous compared to turning the screen on.
Bug: 7299370
Bug: 7139924
Change-Id: I57d13287acd05bd0a48811095bb02dc7bc7cbeb6
Diffstat (limited to 'services/java/com/android/server/power/DisplayPowerController.java')
-rw-r--r-- | services/java/com/android/server/power/DisplayPowerController.java | 72 |
1 files changed, 45 insertions, 27 deletions
diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/java/com/android/server/power/DisplayPowerController.java index a1c1fa6cf7ee..25d2944f934e 100644 --- a/services/java/com/android/server/power/DisplayPowerController.java +++ b/services/java/com/android/server/power/DisplayPowerController.java @@ -271,6 +271,12 @@ final class DisplayPowerController { // When the screen turns on again, we report user activity to the power manager. private boolean mScreenOffBecauseOfProximity; + // True if the screen on is being blocked. + private boolean mScreenOnWasBlocked; + + // The elapsed real time when the screen on was blocked. + private long mScreenOnBlockStartRealTime; + // Set to true if the light sensor is enabled. private boolean mLightSensorEnabled; @@ -513,7 +519,7 @@ final class DisplayPowerController { final Executor executor = AsyncTask.THREAD_POOL_EXECUTOR; Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); mPowerState = new DisplayPowerState( - mElectronBeamAnimatesBacklightConfig ? null : new ElectronBeam(display), + new ElectronBeam(display), new PhotonicModulator(executor, mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT), mSuspendBlocker)); @@ -553,7 +559,6 @@ final class DisplayPowerController { final boolean mustNotify; boolean mustInitialize = false; boolean updateAutoBrightness = mTwilightChanged; - boolean screenOnWasBlocked = false; mTwilightChanged = false; synchronized (mLock) { @@ -662,18 +667,24 @@ 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()) { - if (mPowerRequest.blockScreenOn && !mPowerState.isScreenOn()) { - if (DEBUG) { - Slog.d(TAG, "Blocked screen on while screen currently off."); - } - screenOnWasBlocked = true; + // 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); + + if (mPowerRequest.blockScreenOn + && mPowerState.getElectronBeamLevel() == 0.0f) { + blockScreenOn(); } else { - setScreenOn(true); + unblockScreenOn(); if (USE_ELECTRON_BEAM_ON_ANIMATION) { if (!mElectronBeamOnAnimator.isStarted()) { if (mPowerState.getElectronBeamLevel() == 1.0f) { mPowerState.dismissElectronBeam(); - } else if (mPowerState.prepareElectronBeam(true)) { + } else if (mPowerState.prepareElectronBeam( + mElectronBeamAnimatesBacklightConfig ? + ElectronBeam.MODE_BLANK : + ElectronBeam.MODE_WARM_UP)) { mElectronBeamOnAnimator.start(); } else { mElectronBeamOnAnimator.end(); @@ -684,22 +695,6 @@ final class DisplayPowerController { 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 { // Want screen off. @@ -708,7 +703,10 @@ final class DisplayPowerController { if (!mElectronBeamOffAnimator.isStarted()) { if (mPowerState.getElectronBeamLevel() == 0.0f) { setScreenOn(false); - } else if (mPowerState.prepareElectronBeam(false) + } else if (mPowerState.prepareElectronBeam( + mElectronBeamAnimatesBacklightConfig ? + ElectronBeam.MODE_BLANK : + ElectronBeam.MODE_COOL_DOWN) && mPowerState.isScreenOn()) { mElectronBeamOffAnimator.start(); } else { @@ -723,7 +721,7 @@ final class DisplayPowerController { // We mostly care about the screen state here, ignoring brightness changes // which will be handled asynchronously. if (mustNotify - && !screenOnWasBlocked + && !mScreenOnWasBlocked && !mElectronBeamOnAnimator.isStarted() && !mElectronBeamOffAnimator.isStarted() && mPowerState.waitUntilClean(mCleanListener)) { @@ -740,6 +738,26 @@ final class DisplayPowerController { } } + private void blockScreenOn() { + if (!mScreenOnWasBlocked) { + mScreenOnWasBlocked = true; + if (DEBUG) { + Slog.d(TAG, "Blocked screen on."); + mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime(); + } + } + } + + private void unblockScreenOn() { + if (mScreenOnWasBlocked) { + mScreenOnWasBlocked = false; + if (DEBUG) { + Slog.d(TAG, "Unblocked screen on after " + + (SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime) + " ms"); + } + } + } + private void setScreenOn(boolean on) { if (!mPowerState.isScreenOn() == on) { mPowerState.setScreenOn(on); |