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

Commit 1fd6c336 authored by Dianne Hackborn's avatar Dianne Hackborn Committed by Dave Burke
Browse files

Fix issue #5312624: Lock screen very flickery

The key thing was to fix isVisibleOrBehindKeyguardLw() so that it
wouldn't count a window as not visible if it was just currently
in the process of drawing due to an orientation change.

Also improve logic in deciding when to turn screen on to better ensure
the screen is in a stable state, in particular treating screen off
as a frozen screen and not allowing it to turn on until the
update of the screen due to any config change is done.

Change-Id: If82199f3773270b2d07f9c7de9da2dad8c7b28d7
parent 6ea4da95
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -784,9 +784,14 @@ public interface WindowManagerPolicy {
    public void screenTurningOn(ScreenOnListener screenOnListener);

    /**
     * Return whether the screen is currently on.
     * Return whether the screen is about to turn on or is currently on.
     */
    public boolean isScreenOn();
    public boolean isScreenOnEarly();

    /**
     * Return whether the screen is fully turned on.
     */
    public boolean isScreenOnFully();

    /**
     * Tell the policy that the lid switch has changed state.
+33 −18
Original line number Diff line number Diff line
@@ -127,7 +127,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
import android.view.KeyCharacterMap.FallbackAction;
import android.view.WindowManagerPolicy.ScreenOnListener;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
@@ -287,7 +286,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    int mLidKeyboardAccessibility;
    int mLidNavigationAccessibility;
    int mLongPressOnPowerBehavior = -1;
    boolean mScreenOn = false;
    boolean mScreenOnEarly = false;
    boolean mScreenOnFully = false;
    boolean mOrientationSensorEnabled = false;
    int mCurrentAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
    static final int DEFAULT_ACCELEROMETER_ROTATION = 0;
@@ -547,11 +547,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
        }
        //Could have been invoked due to screen turning on or off or
        //change of the currently visible window's orientation
        if (localLOGV) Log.v(TAG, "Screen status="+mScreenOn+
        if (localLOGV) Log.v(TAG, "Screen status="+mScreenOnEarly+
                ", current orientation="+mCurrentAppOrientation+
                ", SensorEnabled="+mOrientationSensorEnabled);
        boolean disable = true;
        if (mScreenOn) {
        if (mScreenOnEarly) {
            if (needSensorRunningLp()) {
                disable = false;
                //enable listener if not already enabled
@@ -2094,6 +2094,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    /** {@inheritDoc} */
    public void animatingWindowLw(WindowState win,
                                WindowManager.LayoutParams attrs) {
        if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
                + win.isVisibleOrBehindKeyguardLw());
        if (mTopFullscreenOpaqueWindowState == null &&
                win.isVisibleOrBehindKeyguardLw()) {
            if ((attrs.flags & FLAG_FORCE_NOT_FULLSCREEN) != 0) {
@@ -2137,10 +2139,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                : null;

        if (mStatusBar != null) {
            if (localLOGV) Log.i(TAG, "force=" + mForceStatusBar
            if (DEBUG_LAYOUT) Log.i(TAG, "force=" + mForceStatusBar
                    + " top=" + mTopFullscreenOpaqueWindowState);
            if (mForceStatusBar) {
                if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar");
                if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar: forced");
                if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
            } else if (mTopFullscreenOpaqueWindowState != null) {
                if (localLOGV) {
@@ -2168,11 +2170,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                                }
                            }});
                        }
                    } else if (localLOGV) {
                    } else if (DEBUG_LAYOUT) {
                        Log.v(TAG, "Preventing status bar from hiding by policy");
                    }
                } else {
                    if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar");
                    if (DEBUG_LAYOUT) Log.v(TAG, "Showing status bar: top is not fullscreen");
                    if (mStatusBar.showLw(true)) changes |= FINISH_LAYOUT_REDO_LAYOUT;
                }
            }
@@ -2809,7 +2811,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    public void screenTurnedOff(int why) {
        EventLog.writeEvent(70000, 0);
        synchronized (mLock) {
            mScreenOn = false;
            mScreenOnEarly = false;
            mScreenOnFully = false;
        }
        mKeyguardMediator.onScreenTurnedOff(why);
        synchronized (mLock) {
@@ -2831,6 +2834,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                            @Override public void sendResult(Bundle data) {
                                Slog.i(TAG, "Lock screen displayed!");
                                screenOnListener.onScreenOn();
                                synchronized (mLock) {
                                    mScreenOnFully = true;
                                }
                            }
                        });
                    } catch (RemoteException e) {
@@ -2838,11 +2844,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                } else {
                    Slog.i(TAG, "No lock screen!");
                    screenOnListener.onScreenOn();
                    synchronized (mLock) {
                        mScreenOnFully = true;
                    }
                }
            }
        });
        synchronized (mLock) {
            mScreenOn = true;
            mScreenOnEarly = true;
            updateOrientationListenerLp();
            updateLockScreenTimeout();
            updateScreenSaverTimeoutLocked();
@@ -2850,8 +2859,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
    }

    /** {@inheritDoc} */
    public boolean isScreenOn() {
        return mScreenOn;
    public boolean isScreenOnEarly() {
        return mScreenOnEarly;
    }
    
    /** {@inheritDoc} */
    public boolean isScreenOnFully() {
        return mScreenOnFully;
    }
    
    /** {@inheritDoc} */
@@ -3238,7 +3252,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {

        synchronized (mScreenSaverActivator) {
            mHandler.removeCallbacks(mScreenSaverActivator);
            if (mScreenSaverEnabled && mScreenOn && mScreenSaverTimeout > 0) {
            if (mScreenSaverEnabled && mScreenOnEarly && mScreenSaverTimeout > 0) {
                if (localLOGV)
                    Log.v(TAG, "scheduling screensaver for " + mScreenSaverTimeout + "ms from now");
                mHandler.postDelayed(mScreenSaverActivator, mScreenSaverTimeout);
@@ -3246,7 +3260,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                if (localLOGV) {
                    if (mScreenSaverTimeout == 0)
                        Log.v(TAG, "screen saver disabled by user");
                    else if (!mScreenOn)
                    else if (!mScreenOnEarly)
                        Log.v(TAG, "screen saver disabled while screen off");
                    else
                        Log.v(TAG, "screen saver disabled by wakelock");
@@ -3267,7 +3281,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {

    private void updateLockScreenTimeout() {
        synchronized (mScreenLockTimeout) {
            boolean enable = (mAllowLockscreenWhenOn && mScreenOn && mKeyguardMediator.isSecure());
            boolean enable = (mAllowLockscreenWhenOn && mScreenOnEarly && mKeyguardMediator.isSecure());
            if (mLockScreenTimerActive != enable) {
                if (enable) {
                    if (localLOGV) Log.v(TAG, "setting lockscreen timer");
@@ -3476,7 +3490,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {

    public boolean allowKeyRepeat() {
        // disable key repeat when screen is off
        return mScreenOn;
        return mScreenOnEarly;
    }

    private void updateSystemUiVisibility() {
@@ -3532,7 +3546,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
                pw.print(mLidKeyboardAccessibility);
                pw.print(" mLidNavigationAccessibility="); pw.print(mLidNavigationAccessibility);
                pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
        pw.print(prefix); pw.print("mScreenOn="); pw.print(mScreenOn);
        pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
                pw.print(" mScreenOnFully="); pw.print(mScreenOnFully);
                pw.print(" mOrientationSensorEnabled="); pw.print(mOrientationSensorEnabled);
                pw.print(" mHasSoftInput="); pw.println(mHasSoftInput);
        pw.print(prefix); pw.print("mUnrestrictedScreen=("); pw.print(mUnrestrictedScreenLeft);
+1 −1
Original line number Diff line number Diff line
@@ -194,7 +194,7 @@ class AppWindowToken extends WindowToken {

    // This must be called while inside a transaction.
    boolean stepAnimationLocked(long currentTime, int dw, int dh) {
        if (!service.mDisplayFrozen && service.mPolicy.isScreenOn()) {
        if (!service.mDisplayFrozen && service.mPolicy.isScreenOnFully()) {
            // We will run animations as long as the display isn't frozen.

            if (animation == WindowManagerService.sDummyAnimation) {
+19 −14
Original line number Diff line number Diff line
@@ -2199,7 +2199,8 @@ public class WindowManagerService extends IWindowManager.Stub
        // to hold off on removing the window until the animation is done.
        // If the display is frozen, just remove immediately, since the
        // animation wouldn't be seen.
        if (win.mSurface != null && !mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) {
        if (win.mSurface != null && !mDisplayFrozen && mDisplayEnabled
                && mPolicy.isScreenOnFully()) {
            // If we are not currently running the exit animation, we
            // need to see about starting one.
            if (wasVisible=win.isWinVisibleLw()) {
@@ -2577,7 +2578,7 @@ public class WindowManagerService extends IWindowManager.Stub
                if (displayed) {
                    if (win.mSurface != null && !win.mDrawPending
                            && !win.mCommitDrawPending && !mDisplayFrozen
                            && mDisplayEnabled && mPolicy.isScreenOn()) {
                            && mDisplayEnabled && mPolicy.isScreenOnFully()) {
                        applyEnterAnimationLocked(win);
                    }
                    if ((win.mAttrs.flags
@@ -2870,7 +2871,7 @@ public class WindowManagerService extends IWindowManager.Stub
        // frozen, there is no reason to animate and it can cause strange
        // artifacts when we unfreeze the display if some different animation
        // is running.
        if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) {
        if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully()) {
            int anim = mPolicy.selectAnimationLw(win, transit);
            int attr = -1;
            Animation a = null;
@@ -2956,7 +2957,7 @@ public class WindowManagerService extends IWindowManager.Stub
        // frozen, there is no reason to animate and it can cause strange
        // artifacts when we unfreeze the display if some different animation
        // is running.
        if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) {
        if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully()) {
            Animation a;
            if (mNextAppTransitionPackage != null) {
                a = loadAnimation(mNextAppTransitionPackage, enter ?
@@ -3522,7 +3523,7 @@ public class WindowManagerService extends IWindowManager.Stub
            if (DEBUG_APP_TRANSITIONS) Slog.v(
                    TAG, "Prepare app transition: transit=" + transit
                    + " mNextAppTransition=" + mNextAppTransition);
            if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()) {
            if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully()) {
                if (mNextAppTransition == WindowManagerPolicy.TRANSIT_UNSET
                        || mNextAppTransition == WindowManagerPolicy.TRANSIT_NONE) {
                    mNextAppTransition = transit;
@@ -3606,7 +3607,7 @@ public class WindowManagerService extends IWindowManager.Stub
            // If the display is frozen, we won't do anything until the
            // actual window is displayed so there is no reason to put in
            // the starting window.
            if (mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOn()) {
            if (mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOnFully()) {
                return;
            }

@@ -3888,7 +3889,7 @@ public class WindowManagerService extends IWindowManager.Stub

            // If we are preparing an app transition, then delay changing
            // the visibility of this token until we execute that transition.
            if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOn()
            if (!mDisplayFrozen && mDisplayEnabled && mPolicy.isScreenOnFully()
                    && mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
                // Already in requested state, don't do anything more.
                if (wtoken.hiddenRequested != visible) {
@@ -4016,7 +4017,7 @@ public class WindowManagerService extends IWindowManager.Stub
        }

        synchronized(mWindowMap) {
            if (configChanges == 0 && !mDisplayFrozen && mPolicy.isScreenOn()) {
            if (configChanges == 0 && !mDisplayFrozen && mPolicy.isScreenOnFully()) {
                if (DEBUG_ORIENTATION) Slog.v(TAG, "Skipping set freeze of " + token);
                return;
            }
@@ -8137,10 +8138,10 @@ public class WindowManagerService extends IWindowManager.Stub

                            w.mLastContentInsets.set(w.mContentInsets);
                            w.mLastVisibleInsets.set(w.mVisibleInsets);
                            // If the screen is currently frozen, then keep
                            // it frozen until this window draws at its new
                            // If the screen is currently frozen or off, then keep
                            // it frozen/off until this window draws at its new
                            // orientation.
                            if (mDisplayFrozen) {
                            if (mDisplayFrozen || !mPolicy.isScreenOnFully()) {
                                if (DEBUG_ORIENTATION) Slog.v(TAG,
                                        "Resizing while display frozen: " + w);
                                w.mOrientationChanging = true;
@@ -8408,7 +8409,7 @@ public class WindowManagerService extends IWindowManager.Stub

            if (mDimAnimator != null && mDimAnimator.mDimShown) {
                animating |= mDimAnimator.updateSurface(dimming, currentTime,
                        mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOn());
                        mDisplayFrozen || !mDisplayEnabled || !mPolicy.isScreenOnFully());
            }

            if (!blurring && mBlurShown) {
@@ -8604,10 +8605,14 @@ public class WindowManagerService extends IWindowManager.Stub
                    WindowManagerPolicy.USE_LAST_ROTATION, 0, false);
            if (changed) {
                mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
            } else {
                updateRotation = false;
            }
        }

        if (orientationChangeComplete && !needRelayout && !updateRotation) {
            checkDrawnWindowsLocked();
        }

        // Check to see if we are now in a state where the screen should
        // be enabled, because the window obscured flags have changed.
@@ -8925,7 +8930,7 @@ public class WindowManagerService extends IWindowManager.Stub
            return;
        }

        if (mDisplay == null || !mPolicy.isScreenOn()) {
        if (mDisplay == null || !mPolicy.isScreenOnFully()) {
            // No need to freeze the screen before the system is ready or if
            // the screen is off.
            return;
+14 −7
Original line number Diff line number Diff line
@@ -870,7 +870,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
    // This must be called while inside a transaction.  Returns true if
    // there is more animation to run.
    boolean stepAnimationLocked(long currentTime, int dw, int dh) {
        if (!mService.mDisplayFrozen && mService.mPolicy.isScreenOn()) {
        if (!mService.mDisplayFrozen && mService.mPolicy.isScreenOnFully()) {
            // We will run animations as long as the display isn't frozen.

            if (!mDrawPending && !mCommitDrawPending && mAnimation != null) {
@@ -1204,11 +1204,18 @@ final class WindowState implements WindowManagerPolicy.WindowState {
     * mPolicyVisibility.  Ungh.
     */
    public boolean isVisibleOrBehindKeyguardLw() {
        if (mRootToken.waitingToShow &&
                mService.mNextAppTransition != WindowManagerPolicy.TRANSIT_UNSET) {
            return false;
        }
        final AppWindowToken atoken = mAppToken;
        return mSurface != null && !mAttachedHidden
        final boolean animating = atoken != null
                ? (atoken.animation != null) : false;
        return mSurface != null && !mDestroying && !mExiting
                && (atoken == null ? mPolicyVisibility : !atoken.hiddenRequested)
                && !mDrawPending && !mCommitDrawPending
                && !mExiting && !mDestroying;
                && ((!mAttachedHidden && mViewVisibility == View.VISIBLE
                                && !mRootToken.hidden)
                        || mAnimation != null || animating);
    }

    /**
@@ -1351,7 +1358,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
                && (mFrame.top != mLastFrame.top
                        || mFrame.left != mLastFrame.left)
                && (mAttachedWindow == null || !mAttachedWindow.shouldAnimateMove())
                && mService.mPolicy.isScreenOn();
                && mService.mPolicy.isScreenOnFully();
    }

    boolean isFullscreen(int screenWidth, int screenHeight) {
@@ -1436,7 +1443,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {
        if (doAnimation) {
            if (DEBUG_VISIBILITY) Slog.v(WindowManagerService.TAG, "doAnimation: mPolicyVisibility="
                    + mPolicyVisibility + " mAnimation=" + mAnimation);
            if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOn()) {
            if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOnFully()) {
                doAnimation = false;
            } else if (mPolicyVisibility && mAnimation == null) {
                // Check for the case where we are currently visible and
@@ -1462,7 +1469,7 @@ final class WindowState implements WindowManagerPolicy.WindowState {

    boolean hideLw(boolean doAnimation, boolean requestAnim) {
        if (doAnimation) {
            if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOn()) {
            if (mService.mDisplayFrozen || !mService.mPolicy.isScreenOnFully()) {
                doAnimation = false;
            }
        }