Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 08e255c9 authored by Jeff Brown's avatar Jeff Brown Committed by Android Git Automerger
Browse files

am f9205adb: am 3a8effb8: am 9302251e: Merge "Reduce screen on latency,...

am f9205adb: am 3a8effb8: am 9302251e: Merge "Reduce screen on latency, eliminate flashes." into jb-mr1-dev

* commit 'f9205adb':
  Reduce screen on latency, eliminate flashes.
parents 8c8487fd f9205adb
Loading
Loading
Loading
Loading
+45 −27
Original line number Original line Diff line number Diff line
@@ -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;


@@ -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));
@@ -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) {
@@ -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();
@@ -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.
@@ -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 {
@@ -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)) {
@@ -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);
+8 −5
Original line number Original line Diff line number Diff line
@@ -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() {
+8 −17
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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.
@@ -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) {
@@ -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);
            }
            }


+54 −20
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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";
@@ -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();
@@ -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;
    }
    }
@@ -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);
@@ -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.
     *
     *
@@ -148,6 +162,7 @@ final class ElectronBeam {


        destroyScreenshotTexture();
        destroyScreenshotTexture();
        destroyEglSurface();
        destroyEglSurface();
        destroySurface();
        mPrepared = false;
        mPrepared = false;
    }
    }


@@ -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;
        }
        }
@@ -185,8 +208,7 @@ final class ElectronBeam {
        } finally {
        } finally {
            detachEglContext();
            detachEglContext();
        }
        }

        return showSurface(1.0f);
        return showEglSurface();
    }
    }


    /**
    /**
@@ -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,
@@ -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);
        }
        }
@@ -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();
        }
        }
@@ -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;
@@ -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
@@ -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 {
@@ -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();
@@ -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);
+1 −1
Original line number Original line Diff line number Diff line
@@ -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 {
    /**
    /**