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

Commit 540012bf authored by Ady Abraham's avatar Ady Abraham Committed by Beverly
Browse files

Add preferredMinDisplayRefreshRate

Add a new private window attribute for allowing apps to specify the min
display refresh rate in addition to the existing
preferredMaxDisplayRefreshRate. This is useful for use cases such as
keyguard where the refresh rate should be limited to a single value,
and using preferredDisplayModeId would not lock the display
refresh rate, as frame rate override might be enabled.

Test: atest RefreshRatePolicyTest FrameRateSelectionPriorityTests DisplayModeDirectorTest
Bug: 183226498
Bug: 184176119
Change-Id: I343569b3cbccd73001703dca78f0f99e196a4d52
parent e6866889
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -207,6 +207,8 @@ public abstract class DisplayManagerInternal {
     * has a preference.
     * @param requestedModeId The preferred mode id for the top-most visible window that has a
     * preference.
     * @param requestedMinRefreshRate The preferred lowest refresh rate for the top-most visible
     *                                window that has a preference.
     * @param requestedMaxRefreshRate The preferred highest refresh rate for the top-most visible
     *                                window that has a preference.
     * @param requestedMinimalPostProcessing The preferred minimal post processing setting for the
@@ -216,8 +218,9 @@ public abstract class DisplayManagerInternal {
     * prior to call to performTraversalInTransactionFromWindowManager.
     */
    public abstract void setDisplayProperties(int displayId, boolean hasContent,
            float requestedRefreshRate, int requestedModeId, float requestedMaxRefreshRate,
            boolean requestedMinimalPostProcessing, boolean inTraversal);
            float requestedRefreshRate, int requestedModeId, float requestedMinRefreshRate,
            float requestedMaxRefreshRate, boolean requestedMinimalPostProcessing,
            boolean inTraversal);

    /**
     * Applies an offset to the contents of a display, for example to avoid burn-in.
+22 −1
Original line number Diff line number Diff line
@@ -3022,6 +3022,14 @@ public interface WindowManager extends ViewManager {
         */
        public int preferredDisplayModeId;

        /**
         * The min display refresh rate while the window is in focus.
         *
         * This value is ignored if {@link #preferredDisplayModeId} is set.
         * @hide
         */
        public float preferredMinDisplayRefreshRate;

        /**
         * The max display refresh rate while the window is in focus.
         *
@@ -3781,6 +3789,7 @@ public interface WindowManager extends ViewManager {
            out.writeInt(screenOrientation);
            out.writeFloat(preferredRefreshRate);
            out.writeInt(preferredDisplayModeId);
            out.writeFloat(preferredMinDisplayRefreshRate);
            out.writeFloat(preferredMaxDisplayRefreshRate);
            out.writeInt(systemUiVisibility);
            out.writeInt(subtreeSystemUiVisibility);
@@ -3852,6 +3861,7 @@ public interface WindowManager extends ViewManager {
            screenOrientation = in.readInt();
            preferredRefreshRate = in.readFloat();
            preferredDisplayModeId = in.readInt();
            preferredMinDisplayRefreshRate = in.readFloat();
            preferredMaxDisplayRefreshRate = in.readFloat();
            systemUiVisibility = in.readInt();
            subtreeSystemUiVisibility = in.readInt();
@@ -3931,7 +3941,9 @@ public interface WindowManager extends ViewManager {
        /** {@hide} */
        public static final int BLUR_BEHIND_RADIUS_CHANGED = 1 << 29;
        /** {@hide} */
        public static final int PREFERRED_MAX_DISPLAY_REFRESH_RATE = 1 << 30;
        public static final int PREFERRED_MIN_DISPLAY_REFRESH_RATE = 1 << 30;
        /** {@hide} */
        public static final int PREFERRED_MAX_DISPLAY_REFRESH_RATE = 1 << 31;

        // internal buffer to backup/restore parameters under compatibility mode.
        private int[] mCompatibilityParamsBackup = null;
@@ -4063,6 +4075,11 @@ public interface WindowManager extends ViewManager {
                changes |= PREFERRED_DISPLAY_MODE_ID;
            }

            if (preferredMinDisplayRefreshRate != o.preferredMinDisplayRefreshRate) {
                preferredMinDisplayRefreshRate = o.preferredMinDisplayRefreshRate;
                changes |= PREFERRED_MIN_DISPLAY_REFRESH_RATE;
            }

            if (preferredMaxDisplayRefreshRate != o.preferredMaxDisplayRefreshRate) {
                preferredMaxDisplayRefreshRate = o.preferredMaxDisplayRefreshRate;
                changes |= PREFERRED_MAX_DISPLAY_REFRESH_RATE;
@@ -4272,6 +4289,10 @@ public interface WindowManager extends ViewManager {
                sb.append(" preferredDisplayMode=");
                sb.append(preferredDisplayModeId);
            }
            if (preferredMinDisplayRefreshRate != 0) {
                sb.append(" preferredMinDisplayRefreshRate=");
                sb.append(preferredMinDisplayRefreshRate);
            }
            if (preferredMaxDisplayRefreshRate != 0) {
                sb.append(" preferredMaxDisplayRefreshRate=");
                sb.append(preferredMaxDisplayRefreshRate);
+9 −7
Original line number Diff line number Diff line
@@ -1506,8 +1506,9 @@ public final class DisplayManagerService extends SystemService {
    }

    private void setDisplayPropertiesInternal(int displayId, boolean hasContent,
            float requestedRefreshRate, int requestedModeId, float requestedMaxRefreshRate,
            boolean preferMinimalPostProcessing, boolean inTraversal) {
            float requestedRefreshRate, int requestedModeId, float requestedMinRefreshRate,
            float requestedMaxRefreshRate, boolean preferMinimalPostProcessing,
            boolean inTraversal) {
        synchronized (mSyncRoot) {
            final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
            if (display == null) {
@@ -1538,7 +1539,7 @@ public final class DisplayManagerService extends SystemService {
                }
            }
            mDisplayModeDirector.getAppRequestObserver().setAppRequest(
                    displayId, requestedModeId, requestedMaxRefreshRate);
                    displayId, requestedModeId, requestedMinRefreshRate, requestedMaxRefreshRate);

            if (display.getDisplayInfoLocked().minimalPostProcessingSupported) {
                boolean mppRequest = mMinimalPostProcessingAllowed && preferMinimalPostProcessing;
@@ -3208,11 +3209,12 @@ public final class DisplayManagerService extends SystemService {

        @Override
        public void setDisplayProperties(int displayId, boolean hasContent,
                float requestedRefreshRate, int requestedMode, float requestedMaxRefreshRate,
                boolean requestedMinimalPostProcessing, boolean inTraversal) {
                float requestedRefreshRate, int requestedMode, float requestedMinRefreshRate,
                float requestedMaxRefreshRate, boolean requestedMinimalPostProcessing,
                boolean inTraversal) {
            setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,
                    requestedMode, requestedMaxRefreshRate, requestedMinimalPostProcessing,
                    inTraversal);
                    requestedMode, requestedMinRefreshRate, requestedMaxRefreshRate,
                    requestedMinimalPostProcessing, inTraversal);
        }

        @Override
+42 −27
Original line number Diff line number Diff line
@@ -913,10 +913,12 @@ public class DisplayModeDirector {
        // It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
        public static final int PRIORITY_USER_SETTING_MIN_REFRESH_RATE = 2;

        // APP_REQUEST_MAX_REFRESH_RATE is used to for internal apps to limit the refresh
        // APP_REQUEST_REFRESH_RATE_RANGE is used to for internal apps to limit the refresh
        // rate in certain cases, mostly to preserve power.
        // It votes to [0, APP_REQUEST_MAX_REFRESH_RATE].
        public static final int PRIORITY_APP_REQUEST_MAX_REFRESH_RATE = 3;
        // @see android.view.WindowManager.LayoutParams#preferredMinRefreshRate
        // @see android.view.WindowManager.LayoutParams#preferredMaxRefreshRate
        // It votes to [preferredMinRefreshRate, preferredMaxRefreshRate].
        public static final int PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE = 3;

        // We split the app request into different priorities in case we can satisfy one desire
        // without the other.
@@ -967,7 +969,7 @@ public class DisplayModeDirector {
        // The cutoff for the app request refresh rate range. Votes with priorities lower than this
        // value will not be considered when constructing the app request refresh rate range.
        public static final int APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF =
                PRIORITY_APP_REQUEST_MAX_REFRESH_RATE;
                PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE;

        /**
         * A value signifying an invalid width or height in a vote.
@@ -1035,8 +1037,8 @@ public class DisplayModeDirector {
            switch (priority) {
                case PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE:
                    return "PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE";
                case PRIORITY_APP_REQUEST_MAX_REFRESH_RATE:
                    return "PRIORITY_APP_REQUEST_MAX_REFRESH_RATE";
                case PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE:
                    return "PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE";
                case PRIORITY_APP_REQUEST_SIZE:
                    return "PRIORITY_APP_REQUEST_SIZE";
                case PRIORITY_DEFAULT_REFRESH_RATE:
@@ -1233,17 +1235,19 @@ public class DisplayModeDirector {

    final class AppRequestObserver {
        private final SparseArray<Display.Mode> mAppRequestedModeByDisplay;
        private final SparseArray<Float> mAppPreferredMaxRefreshRateByDisplay;
        private final SparseArray<RefreshRateRange> mAppPreferredRefreshRateRangeByDisplay;

        AppRequestObserver() {
            mAppRequestedModeByDisplay = new SparseArray<>();
            mAppPreferredMaxRefreshRateByDisplay = new SparseArray<>();
            mAppPreferredRefreshRateRangeByDisplay = new SparseArray<>();
        }

        public void setAppRequest(int displayId, int modeId, float requestedMaxRefreshRate) {
        public void setAppRequest(int displayId, int modeId, float requestedMinRefreshRateRange,
                float requestedMaxRefreshRateRange) {
            synchronized (mLock) {
                setAppRequestedModeLocked(displayId, modeId);
                setAppPreferredMaxRefreshRateLocked(displayId, requestedMaxRefreshRate);
                setAppPreferredRefreshRateRangeLocked(displayId, requestedMinRefreshRateRange,
                        requestedMaxRefreshRateRange);
            }
        }

@@ -1272,26 +1276,36 @@ public class DisplayModeDirector {
            updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_SIZE, sizeVote);
        }

        private void setAppPreferredMaxRefreshRateLocked(int displayId,
                float requestedMaxRefreshRate) {
        private void setAppPreferredRefreshRateRangeLocked(int displayId,
                float requestedMinRefreshRateRange, float requestedMaxRefreshRateRange) {
            final Vote vote;
            final Float requestedMaxRefreshRateVote =
                    requestedMaxRefreshRate > 0
                            ? new Float(requestedMaxRefreshRate) : null;
            if (Objects.equals(requestedMaxRefreshRateVote,
                    mAppPreferredMaxRefreshRateByDisplay.get(displayId))) {

            RefreshRateRange refreshRateRange = null;
            if (requestedMinRefreshRateRange > 0 || requestedMaxRefreshRateRange > 0) {
                float min = requestedMinRefreshRateRange;
                float max = requestedMaxRefreshRateRange > 0
                        ? requestedMaxRefreshRateRange : Float.POSITIVE_INFINITY;
                refreshRateRange = new RefreshRateRange(min, max);
                if (refreshRateRange.min == 0 && refreshRateRange.max == 0) {
                    // requestedMinRefreshRateRange/requestedMaxRefreshRateRange were invalid
                    refreshRateRange = null;
                }
            }

            if (Objects.equals(refreshRateRange,
                    mAppPreferredRefreshRateRangeByDisplay.get(displayId))) {
                return;
            }

            if (requestedMaxRefreshRate > 0) {
                mAppPreferredMaxRefreshRateByDisplay.put(displayId, requestedMaxRefreshRateVote);
                vote = Vote.forRefreshRates(0, requestedMaxRefreshRate);
            if (refreshRateRange != null) {
                mAppPreferredRefreshRateRangeByDisplay.put(displayId, refreshRateRange);
                vote = Vote.forRefreshRates(refreshRateRange.min, refreshRateRange.max);
            } else {
                mAppPreferredMaxRefreshRateByDisplay.remove(displayId);
                mAppPreferredRefreshRateRangeByDisplay.remove(displayId);
                vote = null;
            }
            synchronized (mLock) {
                updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_MAX_REFRESH_RATE, vote);
                updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE, vote);
            }
        }

@@ -1316,11 +1330,12 @@ public class DisplayModeDirector {
                final Display.Mode mode = mAppRequestedModeByDisplay.valueAt(i);
                pw.println("    " + id + " -> " + mode);
            }
            pw.println("    mAppPreferredMaxRefreshRateByDisplay:");
            for (int i = 0; i < mAppPreferredMaxRefreshRateByDisplay.size(); i++) {
                final int id = mAppPreferredMaxRefreshRateByDisplay.keyAt(i);
                final Float refreshRate = mAppPreferredMaxRefreshRateByDisplay.valueAt(i);
                pw.println("    " + id + " -> " + refreshRate);
            pw.println("    mAppPreferredRefreshRateRangeByDisplay:");
            for (int i = 0; i < mAppPreferredRefreshRateRangeByDisplay.size(); i++) {
                final int id = mAppPreferredRefreshRateRangeByDisplay.keyAt(i);
                final RefreshRateRange refreshRateRange =
                        mAppPreferredRefreshRateRangeByDisplay.valueAt(i);
                pw.println("    " + id + " -> " + refreshRateRange);
            }
        }
    }
+11 −0
Original line number Diff line number Diff line
@@ -914,6 +914,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
                    mTmpApplySurfaceChangesTransactionState.preferredModeId = preferredModeId;
                }

                final float preferredMinRefreshRate = getDisplayPolicy().getRefreshRatePolicy()
                        .getPreferredMinRefreshRate(w);
                if (mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate == 0
                        && preferredMinRefreshRate != 0) {
                    mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate =
                            preferredMinRefreshRate;
                }

                final float preferredMaxRefreshRate = getDisplayPolicy().getRefreshRatePolicy()
                        .getPreferredMaxRefreshRate(w);
                if (mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate == 0
@@ -4321,6 +4329,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
                    mLastHasContent,
                    mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
                    mTmpApplySurfaceChangesTransactionState.preferredModeId,
                    mTmpApplySurfaceChangesTransactionState.preferredMinRefreshRate,
                    mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate,
                    mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing,
                    true /* inTraversal, must call performTraversalInTrans... below */);
@@ -4611,6 +4620,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
        public boolean preferMinimalPostProcessing;
        public float preferredRefreshRate;
        public int preferredModeId;
        public float preferredMinRefreshRate;
        public float preferredMaxRefreshRate;

        void reset() {
@@ -4620,6 +4630,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
            preferMinimalPostProcessing = false;
            preferredRefreshRate = 0;
            preferredModeId = 0;
            preferredMinRefreshRate = 0;
            preferredMaxRefreshRate = 0;
        }
    }
Loading