Loading services/java/com/android/server/power/DisplayPowerController.java +45 −27 Original line number Original line Diff line number Diff line Loading @@ -271,6 +271,12 @@ final class DisplayPowerController { // When the screen turns on again, we report user activity to the power manager. // When the screen turns on again, we report user activity to the power manager. private boolean mScreenOffBecauseOfProximity; 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. // Set to true if the light sensor is enabled. private boolean mLightSensorEnabled; private boolean mLightSensorEnabled; Loading Loading @@ -513,7 +519,7 @@ final class DisplayPowerController { final Executor executor = AsyncTask.THREAD_POOL_EXECUTOR; final Executor executor = AsyncTask.THREAD_POOL_EXECUTOR; Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); mPowerState = new DisplayPowerState( mPowerState = new DisplayPowerState( mElectronBeamAnimatesBacklightConfig ? null : new ElectronBeam(display), new ElectronBeam(display), new PhotonicModulator(executor, new PhotonicModulator(executor, mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT), mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT), mSuspendBlocker)); mSuspendBlocker)); Loading Loading @@ -553,7 +559,6 @@ final class DisplayPowerController { final boolean mustNotify; final boolean mustNotify; boolean mustInitialize = false; boolean mustInitialize = false; boolean updateAutoBrightness = mTwilightChanged; boolean updateAutoBrightness = mTwilightChanged; boolean screenOnWasBlocked = false; mTwilightChanged = false; mTwilightChanged = false; synchronized (mLock) { synchronized (mLock) { Loading Loading @@ -662,18 +667,24 @@ final class DisplayPowerController { // It is relatively short but if we cancel it and switch to the // It is relatively short but if we cancel it and switch to the // on animation immediately then the results are pretty ugly. // on animation immediately then the results are pretty ugly. if (!mElectronBeamOffAnimator.isStarted()) { if (!mElectronBeamOffAnimator.isStarted()) { if (mPowerRequest.blockScreenOn && !mPowerState.isScreenOn()) { // Turn the screen on. The contents of the screen may not yet if (DEBUG) { // be visible if the electron beam has not been dismissed because Slog.d(TAG, "Blocked screen on while screen currently off."); // its last frame of animation is solid black. } screenOnWasBlocked = true; } else { setScreenOn(true); setScreenOn(true); if (mPowerRequest.blockScreenOn && mPowerState.getElectronBeamLevel() == 0.0f) { blockScreenOn(); } else { unblockScreenOn(); if (USE_ELECTRON_BEAM_ON_ANIMATION) { if (USE_ELECTRON_BEAM_ON_ANIMATION) { if (!mElectronBeamOnAnimator.isStarted()) { if (!mElectronBeamOnAnimator.isStarted()) { if (mPowerState.getElectronBeamLevel() == 1.0f) { if (mPowerState.getElectronBeamLevel() == 1.0f) { mPowerState.dismissElectronBeam(); mPowerState.dismissElectronBeam(); } else if (mPowerState.prepareElectronBeam(true)) { } else if (mPowerState.prepareElectronBeam( mElectronBeamAnimatesBacklightConfig ? ElectronBeam.MODE_BLANK : ElectronBeam.MODE_WARM_UP)) { mElectronBeamOnAnimator.start(); mElectronBeamOnAnimator.start(); } else { } else { mElectronBeamOnAnimator.end(); mElectronBeamOnAnimator.end(); Loading @@ -684,22 +695,6 @@ final class DisplayPowerController { mPowerState.dismissElectronBeam(); 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 { } else { // Want screen off. // Want screen off. Loading @@ -708,7 +703,10 @@ final class DisplayPowerController { if (!mElectronBeamOffAnimator.isStarted()) { if (!mElectronBeamOffAnimator.isStarted()) { if (mPowerState.getElectronBeamLevel() == 0.0f) { if (mPowerState.getElectronBeamLevel() == 0.0f) { setScreenOn(false); setScreenOn(false); } else if (mPowerState.prepareElectronBeam(false) } else if (mPowerState.prepareElectronBeam( mElectronBeamAnimatesBacklightConfig ? ElectronBeam.MODE_BLANK : ElectronBeam.MODE_COOL_DOWN) && mPowerState.isScreenOn()) { && mPowerState.isScreenOn()) { mElectronBeamOffAnimator.start(); mElectronBeamOffAnimator.start(); } else { } else { Loading @@ -723,7 +721,7 @@ final class DisplayPowerController { // We mostly care about the screen state here, ignoring brightness changes // We mostly care about the screen state here, ignoring brightness changes // which will be handled asynchronously. // which will be handled asynchronously. if (mustNotify if (mustNotify && !screenOnWasBlocked && !mScreenOnWasBlocked && !mElectronBeamOnAnimator.isStarted() && !mElectronBeamOnAnimator.isStarted() && !mElectronBeamOffAnimator.isStarted() && !mElectronBeamOffAnimator.isStarted() && mPowerState.waitUntilClean(mCleanListener)) { && mPowerState.waitUntilClean(mCleanListener)) { Loading @@ -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) { private void setScreenOn(boolean on) { if (!mPowerState.isScreenOn() == on) { if (!mPowerState.isScreenOn() == on) { mPowerState.setScreenOn(on); mPowerState.setScreenOn(on); Loading services/java/com/android/server/power/DisplayPowerRequest.java +8 −5 Original line number Original line Diff line number Diff line Loading @@ -52,11 +52,14 @@ final class DisplayPowerRequest { // If true, enables automatic brightness control. // If true, enables automatic brightness control. public boolean useAutoBrightness; public boolean useAutoBrightness; // If true, prevents the screen from turning on if it is currently off. // If true, prevents the screen from completely turning on if it is currently off. // The display does not enter a "ready" state if this flag is true and the screen // The display does not enter a "ready" state if this flag is true and screen on is // is off and is being prevented from turning on. The window manager policy blocks // blocked. The window manager policy blocks screen on while it prepares the keyguard to // screen on while it prepares the keyguard to prevent the user from seeing // prevent the user from seeing intermediate updates. // intermediate updates. // // Technically, we may not block the screen itself from turning on (because that introduces // extra unnecessary latency) but we do prevent content on screen from becoming // visible to the user. public boolean blockScreenOn; public boolean blockScreenOn; public DisplayPowerRequest() { public DisplayPowerRequest() { Loading services/java/com/android/server/power/DisplayPowerState.java +8 −17 Original line number Original line Diff line number Diff line Loading @@ -50,7 +50,7 @@ final class DisplayPowerState { private static final int DIRTY_BRIGHTNESS = 1 << 2; private static final int DIRTY_BRIGHTNESS = 1 << 2; private final Choreographer mChoreographer; private final Choreographer mChoreographer; private final ElectronBeam mElectronBeam; // may be null if only animating backlights private final ElectronBeam mElectronBeam; private final PhotonicModulator mScreenBrightnessModulator; private final PhotonicModulator mScreenBrightnessModulator; private int mDirty; private int mDirty; Loading Loading @@ -130,27 +130,20 @@ final class DisplayPowerState { * This method should be called before starting an animation because it * This method should be called before starting an animation because it * can take a fair amount of time to prepare the electron beam surface. * can take a fair amount of time to prepare the electron beam surface. * * * @param warmUp True if the electron beam should start warming up. * @param mode The electron beam animation mode to prepare. * @return True if the electron beam was prepared. * @return True if the electron beam was prepared. */ */ public boolean prepareElectronBeam(boolean warmUp) { public boolean prepareElectronBeam(int mode) { if (mElectronBeam != null) { boolean success = mElectronBeam.prepare(warmUp); invalidate(DIRTY_ELECTRON_BEAM); invalidate(DIRTY_ELECTRON_BEAM); return success; return mElectronBeam.prepare(mode); } else { return true; } } } /** /** * Dismisses the electron beam surface. * Dismisses the electron beam surface. */ */ public void dismissElectronBeam() { public void dismissElectronBeam() { if (mElectronBeam != null) { mElectronBeam.dismiss(); mElectronBeam.dismiss(); } } } /** /** * Sets the level of the electron beam steering current. * Sets the level of the electron beam steering current. Loading Loading @@ -230,10 +223,8 @@ final class DisplayPowerState { pw.println(" mScreenBrightness=" + mScreenBrightness); pw.println(" mScreenBrightness=" + mScreenBrightness); pw.println(" mElectronBeamLevel=" + mElectronBeamLevel); pw.println(" mElectronBeamLevel=" + mElectronBeamLevel); if (mElectronBeam != null) { mElectronBeam.dump(pw); mElectronBeam.dump(pw); } } } private void invalidate(int dirty) { private void invalidate(int dirty) { if (mDirty == 0) { if (mDirty == 0) { Loading @@ -251,7 +242,7 @@ final class DisplayPowerState { PowerManagerService.nativeSetScreenState(false); PowerManagerService.nativeSetScreenState(false); } } if ((mDirty & DIRTY_ELECTRON_BEAM) != 0 && mElectronBeam != null) { if ((mDirty & DIRTY_ELECTRON_BEAM) != 0) { mElectronBeam.draw(mElectronBeamLevel); mElectronBeam.draw(mElectronBeamLevel); } } Loading services/java/com/android/server/power/ElectronBeam.java +54 −20 Original line number Original line Diff line number Diff line Loading @@ -26,7 +26,6 @@ import android.opengl.EGLSurface; import android.opengl.GLES10; import android.opengl.GLES10; import android.opengl.GLUtils; import android.opengl.GLUtils; import android.os.Looper; import android.os.Looper; import android.os.Process; import android.util.FloatMath; import android.util.FloatMath; import android.util.Slog; import android.util.Slog; import android.view.Display; import android.view.Display; Loading @@ -41,12 +40,13 @@ import java.nio.FloatBuffer; /** /** * Bzzzoooop! *crackle* * Bzzzoooop! *crackle* * * <p> * Animates a screen transition from on to off or off to on by applying * Animates a screen transition from on to off or off to on by applying * some GL transformations to a screenshot. * some GL transformations to a screenshot. * * </p><p> * This component must only be created or accessed by the {@link Looper} thread * This component must only be created or accessed by the {@link Looper} thread * that belongs to the {@link DisplayPowerController}. * that belongs to the {@link DisplayPowerController}. * </p> */ */ final class ElectronBeam { final class ElectronBeam { private static final String TAG = "ElectronBeam"; private static final String TAG = "ElectronBeam"; Loading @@ -65,7 +65,7 @@ final class ElectronBeam { // Set to true when the animation context has been fully prepared. // Set to true when the animation context has been fully prepared. private boolean mPrepared; private boolean mPrepared; private boolean mWarmUp; private int mMode; private final Display mDisplay; private final Display mDisplay; private final DisplayInfo mDisplayInfo = new DisplayInfo(); private final DisplayInfo mDisplayInfo = new DisplayInfo(); Loading @@ -90,6 +90,10 @@ final class ElectronBeam { private final FloatBuffer mVertexBuffer = createNativeFloatBuffer(8); private final FloatBuffer mVertexBuffer = createNativeFloatBuffer(8); private final FloatBuffer mTexCoordBuffer = createNativeFloatBuffer(8); private final FloatBuffer mTexCoordBuffer = createNativeFloatBuffer(8); public static final int MODE_WARM_UP = 0; public static final int MODE_COOL_DOWN = 1; public static final int MODE_BLANK = 2; public ElectronBeam(Display display) { public ElectronBeam(Display display) { mDisplay = display; mDisplay = display; } } Loading @@ -98,16 +102,15 @@ final class ElectronBeam { * Warms up the electron beam in preparation for turning on or off. * Warms up the electron beam in preparation for turning on or off. * This method prepares a GL context, and captures a screen shot. * This method prepares a GL context, and captures a screen shot. * * * @param warmUp True if the electron beam is about to be turned on, false if * @param mode The desired mode for the upcoming animation. * it is about to be turned off. * @return True if the electron beam is ready, false if it is uncontrollable. * @return True if the electron beam is ready, false if it is uncontrollable. */ */ public boolean prepare(boolean warmUp) { public boolean prepare(int mode) { if (DEBUG) { if (DEBUG) { Slog.d(TAG, "prepare: warmUp=" + warmUp); Slog.d(TAG, "prepare: mode=" + mode); } } mWarmUp = warmUp; mMode = mode; // Get the display size and adjust it for rotation. // Get the display size and adjust it for rotation. mDisplay.getDisplayInfo(mDisplayInfo); mDisplay.getDisplayInfo(mDisplayInfo); Loading @@ -123,17 +126,28 @@ final class ElectronBeam { } } // Prepare the surface for drawing. // Prepare the surface for drawing. if (!createEglContext() if (!tryPrepare()) { || !createEglSurface() || !captureScreenshotTextureAndSetViewport()) { dismiss(); dismiss(); return false; return false; } } // Done. mPrepared = true; mPrepared = true; return true; return true; } } private boolean tryPrepare() { if (createSurface()) { if (mMode == MODE_BLANK) { return true; } return createEglContext() && createEglSurface() && captureScreenshotTextureAndSetViewport(); } return false; } /** /** * Dismisses the electron beam animation surface and cleans up. * Dismisses the electron beam animation surface and cleans up. * * Loading @@ -148,6 +162,7 @@ final class ElectronBeam { destroyScreenshotTexture(); destroyScreenshotTexture(); destroyEglSurface(); destroyEglSurface(); destroySurface(); mPrepared = false; mPrepared = false; } } Loading @@ -163,6 +178,14 @@ final class ElectronBeam { Slog.d(TAG, "drawFrame: level=" + level); Slog.d(TAG, "drawFrame: level=" + level); } } if (!mPrepared) { return false; } if (mMode == MODE_BLANK) { return showSurface(1.0f - level); } if (!attachEglContext()) { if (!attachEglContext()) { return false; return false; } } Loading @@ -185,8 +208,7 @@ final class ElectronBeam { } finally { } finally { detachEglContext(); detachEglContext(); } } return showSurface(1.0f); return showEglSurface(); } } /** /** Loading Loading @@ -217,7 +239,7 @@ final class ElectronBeam { // bind texture and set blending for drawing planes // bind texture and set blending for drawing planes GLES10.glBindTexture(GLES10.GL_TEXTURE_2D, mTexNames[0]); GLES10.glBindTexture(GLES10.GL_TEXTURE_2D, mTexNames[0]); GLES10.glTexEnvx(GLES10.GL_TEXTURE_ENV, GLES10.GL_TEXTURE_ENV_MODE, GLES10.glTexEnvx(GLES10.GL_TEXTURE_ENV, GLES10.GL_TEXTURE_ENV_MODE, mWarmUp ? GLES10.GL_MODULATE : GLES10.GL_REPLACE); mMode == MODE_WARM_UP ? GLES10.GL_MODULATE : GLES10.GL_REPLACE); GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D, GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D, GLES10.GL_TEXTURE_MAG_FILTER, GLES10.GL_LINEAR); GLES10.GL_TEXTURE_MAG_FILTER, GLES10.GL_LINEAR); GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D, GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D, Loading Loading @@ -251,7 +273,7 @@ final class ElectronBeam { GLES10.glColorMask(true, true, true, true); GLES10.glColorMask(true, true, true, true); // draw the white highlight (we use the last vertices) // draw the white highlight (we use the last vertices) if (!mWarmUp) { if (mMode == MODE_COOL_DOWN) { GLES10.glColor4f(ag, ag, ag, 1.0f); GLES10.glColor4f(ag, ag, ag, 1.0f); GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4); GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4); } } Loading Loading @@ -472,7 +494,7 @@ final class ElectronBeam { } } }*/ }*/ private boolean createEglSurface() { private boolean createSurface() { if (mSurfaceSession == null) { if (mSurfaceSession == null) { mSurfaceSession = new SurfaceSession(); mSurfaceSession = new SurfaceSession(); } } Loading @@ -481,9 +503,15 @@ final class ElectronBeam { try { try { if (mSurface == null) { if (mSurface == null) { try { try { int flags; if (mMode == MODE_BLANK) { flags = Surface.FX_SURFACE_DIM | Surface.HIDDEN; } else { flags = Surface.OPAQUE | Surface.HIDDEN; } mSurface = new Surface(mSurfaceSession, mSurface = new Surface(mSurfaceSession, "ElectronBeam", mDisplayWidth, mDisplayHeight, "ElectronBeam", mDisplayWidth, mDisplayHeight, PixelFormat.OPAQUE, Surface.OPAQUE | Surface.HIDDEN); PixelFormat.OPAQUE, flags); } catch (Surface.OutOfResourcesException ex) { } catch (Surface.OutOfResourcesException ex) { Slog.e(TAG, "Unable to create surface.", ex); Slog.e(TAG, "Unable to create surface.", ex); return false; return false; Loading Loading @@ -514,7 +542,10 @@ final class ElectronBeam { } finally { } finally { Surface.closeTransaction(); Surface.closeTransaction(); } } return true; } private boolean createEglSurface() { if (mEglSurface == null) { if (mEglSurface == null) { int[] eglSurfaceAttribList = new int[] { int[] eglSurfaceAttribList = new int[] { EGL14.EGL_NONE EGL14.EGL_NONE Loading @@ -536,7 +567,9 @@ final class ElectronBeam { } } mEglSurface = null; mEglSurface = null; } } } private void destroySurface() { if (mSurface != null) { if (mSurface != null) { Surface.openTransaction(); Surface.openTransaction(); try { try { Loading @@ -549,11 +582,12 @@ final class ElectronBeam { } } } } private boolean showEglSurface() { private boolean showSurface(float alpha) { if (!mSurfaceVisible) { if (!mSurfaceVisible) { Surface.openTransaction(); Surface.openTransaction(); try { try { mSurface.setLayer(ELECTRON_BEAM_LAYER); mSurface.setLayer(ELECTRON_BEAM_LAYER); mSurface.setAlpha(alpha); mSurface.show(); mSurface.show(); } finally { } finally { Surface.closeTransaction(); Surface.closeTransaction(); Loading Loading @@ -643,7 +677,7 @@ final class ElectronBeam { pw.println(); pw.println(); pw.println("Electron Beam State:"); pw.println("Electron Beam State:"); pw.println(" mPrepared=" + mPrepared); pw.println(" mPrepared=" + mPrepared); pw.println(" mWarmUp=" + mWarmUp); pw.println(" mMode=" + mMode); pw.println(" mDisplayLayerStack=" + mDisplayLayerStack); pw.println(" mDisplayLayerStack=" + mDisplayLayerStack); pw.println(" mDisplayRotation=" + mDisplayRotation); pw.println(" mDisplayRotation=" + mDisplayRotation); pw.println(" mDisplayWidth=" + mDisplayWidth); pw.println(" mDisplayWidth=" + mDisplayWidth); Loading services/java/com/android/server/power/ScreenOnBlocker.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -18,7 +18,7 @@ package com.android.server.power; /** /** * Low-level screen on blocker mechanism which is used to keep the screen off * Low-level screen on blocker mechanism which is used to keep the screen off * until the window manager is ready to show new content. * or the contents of the screen hidden until the window manager is ready to show new content. */ */ interface ScreenOnBlocker { interface ScreenOnBlocker { /** /** Loading Loading
services/java/com/android/server/power/DisplayPowerController.java +45 −27 Original line number Original line Diff line number Diff line Loading @@ -271,6 +271,12 @@ final class DisplayPowerController { // When the screen turns on again, we report user activity to the power manager. // When the screen turns on again, we report user activity to the power manager. private boolean mScreenOffBecauseOfProximity; 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. // Set to true if the light sensor is enabled. private boolean mLightSensorEnabled; private boolean mLightSensorEnabled; Loading Loading @@ -513,7 +519,7 @@ final class DisplayPowerController { final Executor executor = AsyncTask.THREAD_POOL_EXECUTOR; final Executor executor = AsyncTask.THREAD_POOL_EXECUTOR; Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY); mPowerState = new DisplayPowerState( mPowerState = new DisplayPowerState( mElectronBeamAnimatesBacklightConfig ? null : new ElectronBeam(display), new ElectronBeam(display), new PhotonicModulator(executor, new PhotonicModulator(executor, mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT), mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT), mSuspendBlocker)); mSuspendBlocker)); Loading Loading @@ -553,7 +559,6 @@ final class DisplayPowerController { final boolean mustNotify; final boolean mustNotify; boolean mustInitialize = false; boolean mustInitialize = false; boolean updateAutoBrightness = mTwilightChanged; boolean updateAutoBrightness = mTwilightChanged; boolean screenOnWasBlocked = false; mTwilightChanged = false; mTwilightChanged = false; synchronized (mLock) { synchronized (mLock) { Loading Loading @@ -662,18 +667,24 @@ final class DisplayPowerController { // It is relatively short but if we cancel it and switch to the // It is relatively short but if we cancel it and switch to the // on animation immediately then the results are pretty ugly. // on animation immediately then the results are pretty ugly. if (!mElectronBeamOffAnimator.isStarted()) { if (!mElectronBeamOffAnimator.isStarted()) { if (mPowerRequest.blockScreenOn && !mPowerState.isScreenOn()) { // Turn the screen on. The contents of the screen may not yet if (DEBUG) { // be visible if the electron beam has not been dismissed because Slog.d(TAG, "Blocked screen on while screen currently off."); // its last frame of animation is solid black. } screenOnWasBlocked = true; } else { setScreenOn(true); setScreenOn(true); if (mPowerRequest.blockScreenOn && mPowerState.getElectronBeamLevel() == 0.0f) { blockScreenOn(); } else { unblockScreenOn(); if (USE_ELECTRON_BEAM_ON_ANIMATION) { if (USE_ELECTRON_BEAM_ON_ANIMATION) { if (!mElectronBeamOnAnimator.isStarted()) { if (!mElectronBeamOnAnimator.isStarted()) { if (mPowerState.getElectronBeamLevel() == 1.0f) { if (mPowerState.getElectronBeamLevel() == 1.0f) { mPowerState.dismissElectronBeam(); mPowerState.dismissElectronBeam(); } else if (mPowerState.prepareElectronBeam(true)) { } else if (mPowerState.prepareElectronBeam( mElectronBeamAnimatesBacklightConfig ? ElectronBeam.MODE_BLANK : ElectronBeam.MODE_WARM_UP)) { mElectronBeamOnAnimator.start(); mElectronBeamOnAnimator.start(); } else { } else { mElectronBeamOnAnimator.end(); mElectronBeamOnAnimator.end(); Loading @@ -684,22 +695,6 @@ final class DisplayPowerController { mPowerState.dismissElectronBeam(); 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 { } else { // Want screen off. // Want screen off. Loading @@ -708,7 +703,10 @@ final class DisplayPowerController { if (!mElectronBeamOffAnimator.isStarted()) { if (!mElectronBeamOffAnimator.isStarted()) { if (mPowerState.getElectronBeamLevel() == 0.0f) { if (mPowerState.getElectronBeamLevel() == 0.0f) { setScreenOn(false); setScreenOn(false); } else if (mPowerState.prepareElectronBeam(false) } else if (mPowerState.prepareElectronBeam( mElectronBeamAnimatesBacklightConfig ? ElectronBeam.MODE_BLANK : ElectronBeam.MODE_COOL_DOWN) && mPowerState.isScreenOn()) { && mPowerState.isScreenOn()) { mElectronBeamOffAnimator.start(); mElectronBeamOffAnimator.start(); } else { } else { Loading @@ -723,7 +721,7 @@ final class DisplayPowerController { // We mostly care about the screen state here, ignoring brightness changes // We mostly care about the screen state here, ignoring brightness changes // which will be handled asynchronously. // which will be handled asynchronously. if (mustNotify if (mustNotify && !screenOnWasBlocked && !mScreenOnWasBlocked && !mElectronBeamOnAnimator.isStarted() && !mElectronBeamOnAnimator.isStarted() && !mElectronBeamOffAnimator.isStarted() && !mElectronBeamOffAnimator.isStarted() && mPowerState.waitUntilClean(mCleanListener)) { && mPowerState.waitUntilClean(mCleanListener)) { Loading @@ -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) { private void setScreenOn(boolean on) { if (!mPowerState.isScreenOn() == on) { if (!mPowerState.isScreenOn() == on) { mPowerState.setScreenOn(on); mPowerState.setScreenOn(on); Loading
services/java/com/android/server/power/DisplayPowerRequest.java +8 −5 Original line number Original line Diff line number Diff line Loading @@ -52,11 +52,14 @@ final class DisplayPowerRequest { // If true, enables automatic brightness control. // If true, enables automatic brightness control. public boolean useAutoBrightness; public boolean useAutoBrightness; // If true, prevents the screen from turning on if it is currently off. // If true, prevents the screen from completely turning on if it is currently off. // The display does not enter a "ready" state if this flag is true and the screen // The display does not enter a "ready" state if this flag is true and screen on is // is off and is being prevented from turning on. The window manager policy blocks // blocked. The window manager policy blocks screen on while it prepares the keyguard to // screen on while it prepares the keyguard to prevent the user from seeing // prevent the user from seeing intermediate updates. // intermediate updates. // // Technically, we may not block the screen itself from turning on (because that introduces // extra unnecessary latency) but we do prevent content on screen from becoming // visible to the user. public boolean blockScreenOn; public boolean blockScreenOn; public DisplayPowerRequest() { public DisplayPowerRequest() { Loading
services/java/com/android/server/power/DisplayPowerState.java +8 −17 Original line number Original line Diff line number Diff line Loading @@ -50,7 +50,7 @@ final class DisplayPowerState { private static final int DIRTY_BRIGHTNESS = 1 << 2; private static final int DIRTY_BRIGHTNESS = 1 << 2; private final Choreographer mChoreographer; private final Choreographer mChoreographer; private final ElectronBeam mElectronBeam; // may be null if only animating backlights private final ElectronBeam mElectronBeam; private final PhotonicModulator mScreenBrightnessModulator; private final PhotonicModulator mScreenBrightnessModulator; private int mDirty; private int mDirty; Loading Loading @@ -130,27 +130,20 @@ final class DisplayPowerState { * This method should be called before starting an animation because it * This method should be called before starting an animation because it * can take a fair amount of time to prepare the electron beam surface. * can take a fair amount of time to prepare the electron beam surface. * * * @param warmUp True if the electron beam should start warming up. * @param mode The electron beam animation mode to prepare. * @return True if the electron beam was prepared. * @return True if the electron beam was prepared. */ */ public boolean prepareElectronBeam(boolean warmUp) { public boolean prepareElectronBeam(int mode) { if (mElectronBeam != null) { boolean success = mElectronBeam.prepare(warmUp); invalidate(DIRTY_ELECTRON_BEAM); invalidate(DIRTY_ELECTRON_BEAM); return success; return mElectronBeam.prepare(mode); } else { return true; } } } /** /** * Dismisses the electron beam surface. * Dismisses the electron beam surface. */ */ public void dismissElectronBeam() { public void dismissElectronBeam() { if (mElectronBeam != null) { mElectronBeam.dismiss(); mElectronBeam.dismiss(); } } } /** /** * Sets the level of the electron beam steering current. * Sets the level of the electron beam steering current. Loading Loading @@ -230,10 +223,8 @@ final class DisplayPowerState { pw.println(" mScreenBrightness=" + mScreenBrightness); pw.println(" mScreenBrightness=" + mScreenBrightness); pw.println(" mElectronBeamLevel=" + mElectronBeamLevel); pw.println(" mElectronBeamLevel=" + mElectronBeamLevel); if (mElectronBeam != null) { mElectronBeam.dump(pw); mElectronBeam.dump(pw); } } } private void invalidate(int dirty) { private void invalidate(int dirty) { if (mDirty == 0) { if (mDirty == 0) { Loading @@ -251,7 +242,7 @@ final class DisplayPowerState { PowerManagerService.nativeSetScreenState(false); PowerManagerService.nativeSetScreenState(false); } } if ((mDirty & DIRTY_ELECTRON_BEAM) != 0 && mElectronBeam != null) { if ((mDirty & DIRTY_ELECTRON_BEAM) != 0) { mElectronBeam.draw(mElectronBeamLevel); mElectronBeam.draw(mElectronBeamLevel); } } Loading
services/java/com/android/server/power/ElectronBeam.java +54 −20 Original line number Original line Diff line number Diff line Loading @@ -26,7 +26,6 @@ import android.opengl.EGLSurface; import android.opengl.GLES10; import android.opengl.GLES10; import android.opengl.GLUtils; import android.opengl.GLUtils; import android.os.Looper; import android.os.Looper; import android.os.Process; import android.util.FloatMath; import android.util.FloatMath; import android.util.Slog; import android.util.Slog; import android.view.Display; import android.view.Display; Loading @@ -41,12 +40,13 @@ import java.nio.FloatBuffer; /** /** * Bzzzoooop! *crackle* * Bzzzoooop! *crackle* * * <p> * Animates a screen transition from on to off or off to on by applying * Animates a screen transition from on to off or off to on by applying * some GL transformations to a screenshot. * some GL transformations to a screenshot. * * </p><p> * This component must only be created or accessed by the {@link Looper} thread * This component must only be created or accessed by the {@link Looper} thread * that belongs to the {@link DisplayPowerController}. * that belongs to the {@link DisplayPowerController}. * </p> */ */ final class ElectronBeam { final class ElectronBeam { private static final String TAG = "ElectronBeam"; private static final String TAG = "ElectronBeam"; Loading @@ -65,7 +65,7 @@ final class ElectronBeam { // Set to true when the animation context has been fully prepared. // Set to true when the animation context has been fully prepared. private boolean mPrepared; private boolean mPrepared; private boolean mWarmUp; private int mMode; private final Display mDisplay; private final Display mDisplay; private final DisplayInfo mDisplayInfo = new DisplayInfo(); private final DisplayInfo mDisplayInfo = new DisplayInfo(); Loading @@ -90,6 +90,10 @@ final class ElectronBeam { private final FloatBuffer mVertexBuffer = createNativeFloatBuffer(8); private final FloatBuffer mVertexBuffer = createNativeFloatBuffer(8); private final FloatBuffer mTexCoordBuffer = createNativeFloatBuffer(8); private final FloatBuffer mTexCoordBuffer = createNativeFloatBuffer(8); public static final int MODE_WARM_UP = 0; public static final int MODE_COOL_DOWN = 1; public static final int MODE_BLANK = 2; public ElectronBeam(Display display) { public ElectronBeam(Display display) { mDisplay = display; mDisplay = display; } } Loading @@ -98,16 +102,15 @@ final class ElectronBeam { * Warms up the electron beam in preparation for turning on or off. * Warms up the electron beam in preparation for turning on or off. * This method prepares a GL context, and captures a screen shot. * This method prepares a GL context, and captures a screen shot. * * * @param warmUp True if the electron beam is about to be turned on, false if * @param mode The desired mode for the upcoming animation. * it is about to be turned off. * @return True if the electron beam is ready, false if it is uncontrollable. * @return True if the electron beam is ready, false if it is uncontrollable. */ */ public boolean prepare(boolean warmUp) { public boolean prepare(int mode) { if (DEBUG) { if (DEBUG) { Slog.d(TAG, "prepare: warmUp=" + warmUp); Slog.d(TAG, "prepare: mode=" + mode); } } mWarmUp = warmUp; mMode = mode; // Get the display size and adjust it for rotation. // Get the display size and adjust it for rotation. mDisplay.getDisplayInfo(mDisplayInfo); mDisplay.getDisplayInfo(mDisplayInfo); Loading @@ -123,17 +126,28 @@ final class ElectronBeam { } } // Prepare the surface for drawing. // Prepare the surface for drawing. if (!createEglContext() if (!tryPrepare()) { || !createEglSurface() || !captureScreenshotTextureAndSetViewport()) { dismiss(); dismiss(); return false; return false; } } // Done. mPrepared = true; mPrepared = true; return true; return true; } } private boolean tryPrepare() { if (createSurface()) { if (mMode == MODE_BLANK) { return true; } return createEglContext() && createEglSurface() && captureScreenshotTextureAndSetViewport(); } return false; } /** /** * Dismisses the electron beam animation surface and cleans up. * Dismisses the electron beam animation surface and cleans up. * * Loading @@ -148,6 +162,7 @@ final class ElectronBeam { destroyScreenshotTexture(); destroyScreenshotTexture(); destroyEglSurface(); destroyEglSurface(); destroySurface(); mPrepared = false; mPrepared = false; } } Loading @@ -163,6 +178,14 @@ final class ElectronBeam { Slog.d(TAG, "drawFrame: level=" + level); Slog.d(TAG, "drawFrame: level=" + level); } } if (!mPrepared) { return false; } if (mMode == MODE_BLANK) { return showSurface(1.0f - level); } if (!attachEglContext()) { if (!attachEglContext()) { return false; return false; } } Loading @@ -185,8 +208,7 @@ final class ElectronBeam { } finally { } finally { detachEglContext(); detachEglContext(); } } return showSurface(1.0f); return showEglSurface(); } } /** /** Loading Loading @@ -217,7 +239,7 @@ final class ElectronBeam { // bind texture and set blending for drawing planes // bind texture and set blending for drawing planes GLES10.glBindTexture(GLES10.GL_TEXTURE_2D, mTexNames[0]); GLES10.glBindTexture(GLES10.GL_TEXTURE_2D, mTexNames[0]); GLES10.glTexEnvx(GLES10.GL_TEXTURE_ENV, GLES10.GL_TEXTURE_ENV_MODE, GLES10.glTexEnvx(GLES10.GL_TEXTURE_ENV, GLES10.GL_TEXTURE_ENV_MODE, mWarmUp ? GLES10.GL_MODULATE : GLES10.GL_REPLACE); mMode == MODE_WARM_UP ? GLES10.GL_MODULATE : GLES10.GL_REPLACE); GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D, GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D, GLES10.GL_TEXTURE_MAG_FILTER, GLES10.GL_LINEAR); GLES10.GL_TEXTURE_MAG_FILTER, GLES10.GL_LINEAR); GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D, GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D, Loading Loading @@ -251,7 +273,7 @@ final class ElectronBeam { GLES10.glColorMask(true, true, true, true); GLES10.glColorMask(true, true, true, true); // draw the white highlight (we use the last vertices) // draw the white highlight (we use the last vertices) if (!mWarmUp) { if (mMode == MODE_COOL_DOWN) { GLES10.glColor4f(ag, ag, ag, 1.0f); GLES10.glColor4f(ag, ag, ag, 1.0f); GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4); GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4); } } Loading Loading @@ -472,7 +494,7 @@ final class ElectronBeam { } } }*/ }*/ private boolean createEglSurface() { private boolean createSurface() { if (mSurfaceSession == null) { if (mSurfaceSession == null) { mSurfaceSession = new SurfaceSession(); mSurfaceSession = new SurfaceSession(); } } Loading @@ -481,9 +503,15 @@ final class ElectronBeam { try { try { if (mSurface == null) { if (mSurface == null) { try { try { int flags; if (mMode == MODE_BLANK) { flags = Surface.FX_SURFACE_DIM | Surface.HIDDEN; } else { flags = Surface.OPAQUE | Surface.HIDDEN; } mSurface = new Surface(mSurfaceSession, mSurface = new Surface(mSurfaceSession, "ElectronBeam", mDisplayWidth, mDisplayHeight, "ElectronBeam", mDisplayWidth, mDisplayHeight, PixelFormat.OPAQUE, Surface.OPAQUE | Surface.HIDDEN); PixelFormat.OPAQUE, flags); } catch (Surface.OutOfResourcesException ex) { } catch (Surface.OutOfResourcesException ex) { Slog.e(TAG, "Unable to create surface.", ex); Slog.e(TAG, "Unable to create surface.", ex); return false; return false; Loading Loading @@ -514,7 +542,10 @@ final class ElectronBeam { } finally { } finally { Surface.closeTransaction(); Surface.closeTransaction(); } } return true; } private boolean createEglSurface() { if (mEglSurface == null) { if (mEglSurface == null) { int[] eglSurfaceAttribList = new int[] { int[] eglSurfaceAttribList = new int[] { EGL14.EGL_NONE EGL14.EGL_NONE Loading @@ -536,7 +567,9 @@ final class ElectronBeam { } } mEglSurface = null; mEglSurface = null; } } } private void destroySurface() { if (mSurface != null) { if (mSurface != null) { Surface.openTransaction(); Surface.openTransaction(); try { try { Loading @@ -549,11 +582,12 @@ final class ElectronBeam { } } } } private boolean showEglSurface() { private boolean showSurface(float alpha) { if (!mSurfaceVisible) { if (!mSurfaceVisible) { Surface.openTransaction(); Surface.openTransaction(); try { try { mSurface.setLayer(ELECTRON_BEAM_LAYER); mSurface.setLayer(ELECTRON_BEAM_LAYER); mSurface.setAlpha(alpha); mSurface.show(); mSurface.show(); } finally { } finally { Surface.closeTransaction(); Surface.closeTransaction(); Loading Loading @@ -643,7 +677,7 @@ final class ElectronBeam { pw.println(); pw.println(); pw.println("Electron Beam State:"); pw.println("Electron Beam State:"); pw.println(" mPrepared=" + mPrepared); pw.println(" mPrepared=" + mPrepared); pw.println(" mWarmUp=" + mWarmUp); pw.println(" mMode=" + mMode); pw.println(" mDisplayLayerStack=" + mDisplayLayerStack); pw.println(" mDisplayLayerStack=" + mDisplayLayerStack); pw.println(" mDisplayRotation=" + mDisplayRotation); pw.println(" mDisplayRotation=" + mDisplayRotation); pw.println(" mDisplayWidth=" + mDisplayWidth); pw.println(" mDisplayWidth=" + mDisplayWidth); Loading
services/java/com/android/server/power/ScreenOnBlocker.java +1 −1 Original line number Original line Diff line number Diff line Loading @@ -18,7 +18,7 @@ package com.android.server.power; /** /** * Low-level screen on blocker mechanism which is used to keep the screen off * Low-level screen on blocker mechanism which is used to keep the screen off * until the window manager is ready to show new content. * or the contents of the screen hidden until the window manager is ready to show new content. */ */ interface ScreenOnBlocker { interface ScreenOnBlocker { /** /** Loading