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

Commit 40234662 authored by chaviw's avatar chaviw
Browse files

Fixed bug with turnScreenOn window flag.

The test
ActivityManagerActivityVisibilityTests#testTurnScreenOnActivity_withRelayout
was failing due to issues with how the turnScreenOn flag was handled.
This change centralizes the logic about when to turn the screen on. The
check for whether the screen should be turned on will happen on each
relayout but is guarded by a flag set in resume. This way the screen can only
have the chance to turn on if a resume was just called.

Change-Id: I0a6e4a11de92fa41c8a49cbfd1b78bd8b38a1b4a
Fixes: 68091612
Test: WindowStateTests
Test: ActivityManagerActivityVisibilityTests
parent 043863ac
Loading
Loading
Loading
Loading
+0 −13
Original line number Original line Diff line number Diff line
@@ -748,19 +748,6 @@ class RootWindowContainer extends WindowContainer<DisplayContent> {
                    (mSustainedPerformanceModeEnabled ? 1 : 0));
                    (mSustainedPerformanceModeEnabled ? 1 : 0));
        }
        }


        if (mService.mTurnOnScreen) {
            if (mService.mAllowTheaterModeWakeFromLayout
                    || Settings.Global.getInt(mService.mContext.getContentResolver(),
                    Settings.Global.THEATER_MODE_ON, 0) == 0) {
                if (DEBUG_VISIBILITY || DEBUG_POWER) {
                    Slog.v(TAG, "Turning screen on after layout!");
                }
                mService.mPowerManager.wakeUp(SystemClock.uptimeMillis(),
                        "android.server.wm:TURN_ON");
            }
            mService.mTurnOnScreen = false;
        }

        if (mUpdateRotation) {
        if (mUpdateRotation) {
            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
            if (DEBUG_ORIENTATION) Slog.d(TAG, "Performing post-rotate rotation");
            // TODO(multi-display): Update rotation for different displays separately.
            // TODO(multi-display): Update rotation for different displays separately.
+0 −2
Original line number Original line Diff line number Diff line
@@ -746,8 +746,6 @@ public class WindowManagerService extends IWindowManager.Stub
    private Session mHoldingScreenOn;
    private Session mHoldingScreenOn;
    private PowerManager.WakeLock mHoldingScreenWakeLock;
    private PowerManager.WakeLock mHoldingScreenWakeLock;


    boolean mTurnOnScreen;

    // Whether or not a layout can cause a wake up when theater mode is enabled.
    // Whether or not a layout can cause a wake up when theater mode is enabled.
    boolean mAllowTheaterModeWakeFromLayout;
    boolean mAllowTheaterModeWakeFromLayout;


+65 −11
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.server.wm;
package com.android.server.wm;


import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;
import static android.os.PowerManager.DRAW_WAKE_LOCK;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.SurfaceControl.Transaction;
import static android.view.SurfaceControl.Transaction;
@@ -166,6 +167,7 @@ import android.os.SystemClock;
import android.os.Trace;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserHandle;
import android.os.WorkSource;
import android.os.WorkSource;
import android.provider.Settings;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import android.util.DisplayMetrics;
import android.util.MergedConfiguration;
import android.util.MergedConfiguration;
@@ -284,7 +286,6 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    int mLayer;
    int mLayer;
    boolean mHaveFrame;
    boolean mHaveFrame;
    boolean mObscured;
    boolean mObscured;
    boolean mTurnOnScreen;


    int mLayoutSeq = -1;
    int mLayoutSeq = -1;


@@ -623,6 +624,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
     */
     */
    private TapExcludeRegionHolder mTapExcludeRegionHolder;
    private TapExcludeRegionHolder mTapExcludeRegionHolder;


    /**
     * Used for testing because the real PowerManager is final.
     */
    private PowerManagerWrapper mPowerManagerWrapper;

    /**
    /**
     * Compares two window sub-layers and returns -1 if the first is lesser than the second in terms
     * Compares two window sub-layers and returns -1 if the first is lesser than the second in terms
     * of z-order and 1 otherwise.
     * of z-order and 1 otherwise.
@@ -652,9 +658,34 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP


    private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;
    private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f;


    interface PowerManagerWrapper {
        void wakeUp(long time, String reason);

        boolean isInteractive();

    }

    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
            WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
            int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow) {
            int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow) {
        this(service, s, c, token, parentWindow, appOp, seq, a, viewVisibility, ownerId,
                ownerCanAddInternalSystemWindow, new PowerManagerWrapper() {
                    @Override
                    public void wakeUp(long time, String reason) {
                        service.mPowerManager.wakeUp(time, reason);
                    }

                    @Override
                    public boolean isInteractive() {
                        return service.mPowerManager.isInteractive();
                    }
                });
    }

    WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
            WindowState parentWindow, int appOp, int seq, WindowManager.LayoutParams a,
            int viewVisibility, int ownerId, boolean ownerCanAddInternalSystemWindow,
            PowerManagerWrapper powerManagerWrapper) {
        super(service);
        super(service);
        mSession = s;
        mSession = s;
        mClient = c;
        mClient = c;
@@ -671,6 +702,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        DeathRecipient deathRecipient = new DeathRecipient();
        DeathRecipient deathRecipient = new DeathRecipient();
        mSeq = seq;
        mSeq = seq;
        mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
        mEnforceSizeCompat = (mAttrs.privateFlags & PRIVATE_FLAG_COMPATIBLE_WINDOW) != 0;
        mPowerManagerWrapper = powerManagerWrapper;
        if (localLOGV) Slog.v(
        if (localLOGV) Slog.v(
            TAG, "Window " + this + " client=" + c.asBinder()
            TAG, "Window " + this + " client=" + c.asBinder()
            + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
            + " token=" + token + " (" + mAttrs.token + ")" + " params=" + a);
@@ -2257,9 +2289,34 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP


    void prepareWindowToDisplayDuringRelayout(boolean wasVisible) {
    void prepareWindowToDisplayDuringRelayout(boolean wasVisible) {
        // We need to turn on screen regardless of visibility.
        // We need to turn on screen regardless of visibility.
        if ((mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0) {
        boolean hasTurnScreenOnFlag = (mAttrs.flags & FLAG_TURN_SCREEN_ON) != 0;
            if (DEBUG_VISIBILITY) Slog.v(TAG, "Relayout window turning screen on: " + this);
        boolean allowTheaterMode =
            mTurnOnScreen = true;
                mService.mAllowTheaterModeWakeFromLayout || Settings.Global.getInt(
                        mService.mContext.getContentResolver(), Settings.Global.THEATER_MODE_ON, 0)
                        == 0;
        boolean canTurnScreenOn = mAppToken == null || mAppToken.canTurnScreenOn();

        // The screen will turn on if the following conditions are met
        // 1. The window has the flag FLAG_TURN_SCREEN_ON
        // 2. The WMS allows theater mode.
        // 3. No AWT or the AWT allows the screen to be turned on. This should only be true once
        // per resume to prevent the screen getting getting turned on for each relayout. Set
        // canTurnScreenOn will be set to false so the window doesn't turn the screen on again
        // during this resume.
        // 4. When the screen is not interactive. This is because when the screen is already
        // interactive, the value may persist until the next animation, which could potentially
        // be occurring while turning off the screen. This would lead to the screen incorrectly
        // turning back on.
        if (hasTurnScreenOnFlag && allowTheaterMode && canTurnScreenOn
                && !mPowerManagerWrapper.isInteractive()) {
            if (DEBUG_VISIBILITY || DEBUG_POWER) {
                Slog.v(TAG, "Relayout window turning screen on: " + this);
            }
            mPowerManagerWrapper.wakeUp(SystemClock.uptimeMillis(),
                    "android.server.wm:TURN_ON");
        }
        if (mAppToken != null) {
            mAppToken.setCanTurnScreenOn(false);
        }
        }


        // If we were already visible, skip rest of preparation.
        // If we were already visible, skip rest of preparation.
@@ -2553,8 +2610,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
                // in wake lock statistics.  So in particular, we don't want to include the
                // in wake lock statistics.  So in particular, we don't want to include the
                // window's hash code as in toString().
                // window's hash code as in toString().
                final CharSequence tag = getWindowTag();
                final CharSequence tag = getWindowTag();
                mDrawLock = mService.mPowerManager.newWakeLock(
                mDrawLock = mService.mPowerManager.newWakeLock(DRAW_WAKE_LOCK, "Window:" + tag);
                        PowerManager.DRAW_WAKE_LOCK, "Window:" + tag);
                mDrawLock.setReferenceCounted(false);
                mDrawLock.setReferenceCounted(false);
                mDrawLock.setWorkSource(new WorkSource(mOwnerUid, mAttrs.packageName));
                mDrawLock.setWorkSource(new WorkSource(mOwnerUid, mAttrs.packageName));
            }
            }
@@ -3303,15 +3359,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
                    pw.print(" mDestroying="); pw.print(mDestroying);
                    pw.print(" mDestroying="); pw.print(mDestroying);
                    pw.print(" mRemoved="); pw.println(mRemoved);
                    pw.print(" mRemoved="); pw.println(mRemoved);
        }
        }
        if (getOrientationChanging() || mAppFreezing || mTurnOnScreen
        if (getOrientationChanging() || mAppFreezing || mReportOrientationChanged) {
                || mReportOrientationChanged) {
            pw.print(prefix); pw.print("mOrientationChanging=");
            pw.print(prefix); pw.print("mOrientationChanging=");
                    pw.print(mOrientationChanging);
                    pw.print(mOrientationChanging);
                    pw.print(" configOrientationChanging=");
                    pw.print(" configOrientationChanging=");
                    pw.print(getLastReportedConfiguration().orientation
                    pw.print(getLastReportedConfiguration().orientation
                            != getConfiguration().orientation);
                            != getConfiguration().orientation);
                    pw.print(" mAppFreezing="); pw.print(mAppFreezing);
                    pw.print(" mAppFreezing="); pw.print(mAppFreezing);
                    pw.print(" mTurnOnScreen="); pw.print(mTurnOnScreen);
                    pw.print(" mReportOrientationChanged="); pw.println(mReportOrientationChanged);
                    pw.print(" mReportOrientationChanged="); pw.println(mReportOrientationChanged);
        }
        }
        if (mLastFreezeDuration != 0) {
        if (mLastFreezeDuration != 0) {
+0 −25
Original line number Original line Diff line number Diff line
@@ -1095,31 +1095,6 @@ class WindowStateAnimator {
                        w.setOrientationChanging(false);
                        w.setOrientationChanging(false);
                    }
                    }
                }
                }
                // We process mTurnOnScreen even for windows which have already
                // been shown, to handle cases where windows are not necessarily
                // hidden while the screen is turning off.
                // TODO(b/63773439): These cases should be eliminated, though we probably still
                // want to process mTurnOnScreen in this way for clarity.
                if (mWin.mTurnOnScreen &&
                        (mWin.mAppToken == null || mWin.mAppToken.canTurnScreenOn())) {
                    if (DEBUG_VISIBILITY) Slog.v(TAG, "Show surface turning screen on: " + mWin);
                    mWin.mTurnOnScreen = false;

                    // The window should only turn the screen on once per resume, but
                    // prepareSurfaceLocked can be called multiple times. Set canTurnScreenOn to
                    // false so the window doesn't turn the screen on again during this resume.
                    if (mWin.mAppToken != null) {
                        mWin.mAppToken.setCanTurnScreenOn(false);
                    }

                    // We do not add {@code SET_TURN_ON_SCREEN} when the screen is already
                    // interactive as the value may persist until the next animation, which could
                    // potentially occurring while turning off the screen. This would lead to the
                    // screen incorrectly turning back on.
                    if (!mService.mPowerManager.isInteractive()) {
                        mService.mTurnOnScreen = true;
                    }
                }
            }
            }
            if (hasSurface()) {
            if (hasSurface()) {
                w.mToken.hasVisible = true;
                w.mToken.hasVisible = true;
+6 −2
Original line number Original line Diff line number Diff line
@@ -40,6 +40,10 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;


/**
/**
 * Tests for the {@link WindowState} class.
 * Tests for the {@link WindowState} class.
@@ -237,11 +241,11 @@ public class WindowStateTests extends WindowTestsBase {
    }
    }


    private void testPrepareWindowToDisplayDuringRelayout(boolean wasVisible) {
    private void testPrepareWindowToDisplayDuringRelayout(boolean wasVisible) {
        reset(mPowerManagerWrapper);
        final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
        final WindowState root = createWindow(null, TYPE_APPLICATION, "root");
        root.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
        root.mAttrs.flags |= WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
        root.mTurnOnScreen = false;


        root.prepareWindowToDisplayDuringRelayout(wasVisible /*wasVisible*/);
        root.prepareWindowToDisplayDuringRelayout(wasVisible /*wasVisible*/);
        assertTrue(root.mTurnOnScreen);
        verify(mPowerManagerWrapper).wakeUp(anyLong(), anyString());
    }
    }
}
}
Loading