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

Commit f54febd8 authored by Ady Abraham's avatar Ady Abraham Committed by Automerger Merge Worker
Browse files

Merge changes from topic "preferredDisplayModeId60120" into sc-dev am: c49b886d

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/14185079

Change-Id: Ib14c8498860ae432f94ff4c6fab201281a4c3968
parents f58222e6 c49b886d
Loading
Loading
Loading
Loading
+141 −68
Original line number Diff line number Diff line
@@ -198,6 +198,8 @@ public class DisplayModeDirector {
        public float maxRefreshRate;
        public int width;
        public int height;
        public boolean disableRefreshRateSwitching;
        public float baseModeRefreshRate;

        VoteSummary() {
            reset();
@@ -208,6 +210,8 @@ public class DisplayModeDirector {
            maxRefreshRate = Float.POSITIVE_INFINITY;
            width = Vote.INVALID_SIZE;
            height = Vote.INVALID_SIZE;
            disableRefreshRateSwitching = false;
            baseModeRefreshRate = 0f;
        }
    }

@@ -229,13 +233,20 @@ public class DisplayModeDirector {
            // For refresh rates, just use the tightest bounds of all the votes
            summary.minRefreshRate = Math.max(summary.minRefreshRate, vote.refreshRateRange.min);
            summary.maxRefreshRate = Math.min(summary.maxRefreshRate, vote.refreshRateRange.max);
            // For display size, use only the first vote we come across (i.e. the highest
            // priority vote that includes the width / height).
            // For display size, disable refresh rate switching and base mode refresh rate use only
            // the first vote we come across (i.e. the highest priority vote that includes the
            // attribute).
            if (summary.height == Vote.INVALID_SIZE && summary.width == Vote.INVALID_SIZE
                    && vote.height > 0 && vote.width > 0) {
                summary.width = vote.width;
                summary.height = vote.height;
            }
            if (!summary.disableRefreshRateSwitching && vote.disableRefreshRateSwitching) {
                summary.disableRefreshRateSwitching = true;
            }
            if (summary.baseModeRefreshRate == 0f && vote.baseModeRefreshRate > 0f) {
                summary.baseModeRefreshRate = vote.baseModeRefreshRate;
            }
        }
    }

@@ -260,13 +271,14 @@ public class DisplayModeDirector {
                return new DesiredDisplayModeSpecs();
            }

            int[] availableModes = new int[]{defaultMode.getModeId()};
            ArrayList<Display.Mode> availableModes = new ArrayList<>();
            availableModes.add(defaultMode);
            VoteSummary primarySummary = new VoteSummary();
            int lowestConsideredPriority = Vote.MIN_PRIORITY;
            int highestConsideredPriority = Vote.MAX_PRIORITY;

            if (mAlwaysRespectAppRequest) {
                lowestConsideredPriority = Vote.PRIORITY_APP_REQUEST_REFRESH_RATE;
                lowestConsideredPriority = Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE;
                highestConsideredPriority = Vote.PRIORITY_APP_REQUEST_SIZE;
            }

@@ -286,16 +298,19 @@ public class DisplayModeDirector {
                }

                availableModes = filterModes(modes, primarySummary);
                if (availableModes.length > 0) {
                if (!availableModes.isEmpty()) {
                    if (mLoggingEnabled) {
                        Slog.w(TAG, "Found available modes=" + Arrays.toString(availableModes)
                        Slog.w(TAG, "Found available modes=" + availableModes
                                + " with lowest priority considered "
                                + Vote.priorityToString(lowestConsideredPriority)
                                + " and constraints: "
                                + "width=" + primarySummary.width
                                + ", height=" + primarySummary.height
                                + ", minRefreshRate=" + primarySummary.minRefreshRate
                                + ", maxRefreshRate=" + primarySummary.maxRefreshRate);
                                + ", maxRefreshRate=" + primarySummary.maxRefreshRate
                                + ", disableRefreshRateSwitching="
                                + primarySummary.disableRefreshRateSwitching
                                + ", baseModeRefreshRate=" + primarySummary.baseModeRefreshRate);
                    }
                    break;
                }
@@ -307,7 +322,10 @@ public class DisplayModeDirector {
                            + "width=" + primarySummary.width
                            + ", height=" + primarySummary.height
                            + ", minRefreshRate=" + primarySummary.minRefreshRate
                            + ", maxRefreshRate=" + primarySummary.maxRefreshRate);
                            + ", maxRefreshRate=" + primarySummary.maxRefreshRate
                            + ", disableRefreshRateSwitching="
                            + primarySummary.disableRefreshRateSwitching
                            + ", baseModeRefreshRate=" + primarySummary.baseModeRefreshRate);
                }

                // If we haven't found anything with the current set of votes, drop the
@@ -332,26 +350,38 @@ public class DisplayModeDirector {
                                appRequestSummary.maxRefreshRate));
            }

            int baseModeId = INVALID_DISPLAY_MODE_ID;
            // Select the base mode id based on the base mode refresh rate, if available, since this
            // will be the mode id the app voted for.
            Display.Mode baseMode = null;
            for (Display.Mode availableMode : availableModes) {
                if (primarySummary.baseModeRefreshRate
                        >= availableMode.getRefreshRate() - FLOAT_TOLERANCE
                        && primarySummary.baseModeRefreshRate
                        <= availableMode.getRefreshRate() + FLOAT_TOLERANCE) {
                    baseMode = availableMode;
                }
            }

            // Select the default mode if available. This is important because SurfaceFlinger
            // can do only seamless switches by default. Some devices (e.g. TV) don't support
            // seamless switching so the mode we select here won't be changed.
            for (int availableMode : availableModes) {
                if (availableMode == defaultMode.getModeId()) {
                    baseModeId = defaultMode.getModeId();
            if (baseMode == null) {
                for (Display.Mode availableMode : availableModes) {
                    if (availableMode.getModeId() == defaultMode.getModeId()) {
                        baseMode = defaultMode;
                        break;
                    }
                }
            }

            // If the application requests a display mode by setting
            // LayoutParams.preferredDisplayModeId, it will be the only available mode and it'll
            // be stored as baseModeId.
            if (baseModeId == INVALID_DISPLAY_MODE_ID && availableModes.length > 0) {
                baseModeId = availableModes[0];
            if (baseMode == null && !availableModes.isEmpty()) {
                baseMode = availableModes.get(0);
            }

            if (baseModeId == INVALID_DISPLAY_MODE_ID) {
            if (baseMode == null) {
                Slog.w(TAG, "Can't find a set of allowed modes which satisfies the votes. Falling"
                        + " back to the default mode. Display = " + displayId + ", votes = " + votes
                        + ", supported modes = " + Arrays.toString(modes));
@@ -363,31 +393,19 @@ public class DisplayModeDirector {
                        new RefreshRateRange(fps, fps));
            }

            if (mModeSwitchingType == DisplayManager.SWITCHING_TYPE_NONE
                    || primarySummary.disableRefreshRateSwitching) {
                float fps = baseMode.getRefreshRate();
                primarySummary.minRefreshRate = primarySummary.maxRefreshRate = fps;
                if (mModeSwitchingType == DisplayManager.SWITCHING_TYPE_NONE) {
                Display.Mode baseMode = null;
                for (Display.Mode mode : modes) {
                    if (mode.getModeId() == baseModeId) {
                        baseMode = mode;
                        break;
                    appRequestSummary.minRefreshRate = appRequestSummary.maxRefreshRate = fps;
                }
            }
                if (baseMode == null) {
                    // This should never happen.
                    throw new IllegalStateException(
                            "The base mode with id " + baseModeId
                                    + " is not in the list of supported modes.");
                }
                float fps = baseMode.getRefreshRate();
                return new DesiredDisplayModeSpecs(baseModeId,
                        /*allowGroupSwitching */ false,
                        new RefreshRateRange(fps, fps),
                        new RefreshRateRange(fps, fps));
            }

            boolean allowGroupSwitching =
                    mModeSwitchingType == DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS;

            return new DesiredDisplayModeSpecs(baseModeId,
            return new DesiredDisplayModeSpecs(baseMode.getModeId(),
                    allowGroupSwitching,
                    new RefreshRateRange(
                            primarySummary.minRefreshRate, primarySummary.maxRefreshRate),
@@ -396,8 +414,10 @@ public class DisplayModeDirector {
        }
    }

    private int[] filterModes(Display.Mode[] supportedModes, VoteSummary summary) {
    private ArrayList<Display.Mode> filterModes(Display.Mode[] supportedModes,
            VoteSummary summary) {
        ArrayList<Display.Mode> availableModes = new ArrayList<>();
        boolean missingBaseModeRefreshRate = summary.baseModeRefreshRate > 0f;
        for (Display.Mode mode : supportedModes) {
            if (mode.getPhysicalWidth() != summary.width
                    || mode.getPhysicalHeight() != summary.height) {
@@ -426,13 +446,16 @@ public class DisplayModeDirector {
                continue;
            }
            availableModes.add(mode);
            if (mode.getRefreshRate() >= summary.baseModeRefreshRate - FLOAT_TOLERANCE
                    && mode.getRefreshRate() <= summary.baseModeRefreshRate + FLOAT_TOLERANCE) {
                missingBaseModeRefreshRate = false;
            }
        final int size = availableModes.size();
        int[] availableModeIds = new int[size];
        for (int i = 0; i < size; i++) {
            availableModeIds[i] = availableModes.get(i).getModeId();
        }
        return availableModeIds;
        if (missingBaseModeRefreshRate) {
            return new ArrayList<>();
        }

        return availableModes;
    }

    /**
@@ -912,11 +935,10 @@ public class DisplayModeDirector {
        // by all other considerations. It acts to set a default frame rate for a device.
        public static final int PRIORITY_DEFAULT_REFRESH_RATE = 0;

        // FLICKER votes for a single refresh rate like [60,60], [90,90] or null.
        // If the higher voters result is a range, it will fix the rate to a single choice.
        // It's used to avoid refresh rate switches in certain conditions which may result in the
        // user seeing the display flickering when the switches occur.
        public static final int PRIORITY_FLICKER = 1;
        // PRIORITY_FLICKER_REFRESH_RATE votes for a single refresh rate like [60,60], [90,90] or
        // null. It is used to set a preferred refresh rate value in case the higher priority votes
        // result is a range.
        public static final int PRIORITY_FLICKER_REFRESH_RATE = 1;

        // SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate.
        // It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
@@ -933,9 +955,14 @@ public class DisplayModeDirector {
        // Application can specify preferred refresh rate with below attrs.
        // @see android.view.WindowManager.LayoutParams#preferredRefreshRate
        // @see android.view.WindowManager.LayoutParams#preferredDisplayModeId
        // System also forces some apps like denylisted app to run at a lower refresh rate.
        // These translates into votes for the base mode refresh rate and resolution to be
        // used by SurfaceFlinger as the policy of choosing the display mode. The system also
        // forces some apps like denylisted app to run at a lower refresh rate.
        // @see android.R.array#config_highRefreshRateBlacklist
        public static final int PRIORITY_APP_REQUEST_REFRESH_RATE = 4;
        // The preferred refresh rate is set on the main surface of the app outside of
        // DisplayModeDirector.
        // @see com.android.server.wm.WindowState#updateFrameRateSelectionPriorityIfNeeded
        public static final int PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE = 4;
        public static final int PRIORITY_APP_REQUEST_SIZE = 5;

        // SETTING_PEAK_REFRESH_RATE has a high priority and will restrict the bounds of the rest
@@ -945,9 +972,15 @@ public class DisplayModeDirector {
        // LOW_POWER_MODE force display to [0, 60HZ] if Settings.Global.LOW_POWER_MODE is on.
        public static final int PRIORITY_LOW_POWER_MODE = 7;

        // PRIORITY_FLICKER_REFRESH_RATE_SWITCH votes for disabling refresh rate switching. If the
        // higher priority voters' result is a range, it will fix the rate to a single choice.
        // It's used to avoid refresh rate switches in certain conditions which may result in the
        // user seeing the display flickering when the switches occur.
        public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 8;

        // The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order
        // to function, so this needs to be the highest priority of all votes.
        public static final int PRIORITY_UDFPS = 8;
        public static final int PRIORITY_UDFPS = 9;

        // Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and
        // APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString.
@@ -978,34 +1011,64 @@ public class DisplayModeDirector {
         */
        public final RefreshRateRange refreshRateRange;

        /**
         * Whether refresh rate switching should be disabled (i.e. the refresh rate range is
         * a single value).
         */
        public final boolean disableRefreshRateSwitching;

        /**
         * The base mode refresh rate to be used for this display. This would be used when deciding
         * the base mode id.
         */
        public final float baseModeRefreshRate;

        public static Vote forRefreshRates(float minRefreshRate, float maxRefreshRate) {
            return new Vote(INVALID_SIZE, INVALID_SIZE, minRefreshRate, maxRefreshRate);
            return new Vote(INVALID_SIZE, INVALID_SIZE, minRefreshRate, maxRefreshRate,
                    minRefreshRate == maxRefreshRate, 0f);
        }

        public static Vote forSize(int width, int height) {
            return new Vote(width, height, 0f, Float.POSITIVE_INFINITY);
            return new Vote(width, height, 0f, Float.POSITIVE_INFINITY, false,
                    0f);
        }

        public static Vote forDisableRefreshRateSwitching() {
            return new Vote(INVALID_SIZE, INVALID_SIZE, 0f, Float.POSITIVE_INFINITY, true,
                    0f);
        }

        public static Vote forBaseModeRefreshRate(float baseModeRefreshRate) {
            return new Vote(INVALID_SIZE, INVALID_SIZE, 0f, Float.POSITIVE_INFINITY, false,
                    baseModeRefreshRate);
        }

        private Vote(int width, int height,
                float minRefreshRate, float maxRefreshRate) {
                float minRefreshRate, float maxRefreshRate,
                boolean disableRefreshRateSwitching,
                float baseModeRefreshRate) {
            this.width = width;
            this.height = height;
            this.refreshRateRange =
                    new RefreshRateRange(minRefreshRate, maxRefreshRate);
            this.disableRefreshRateSwitching = disableRefreshRateSwitching;
            this.baseModeRefreshRate = baseModeRefreshRate;
        }

        public static String priorityToString(int priority) {
            switch (priority) {
                case PRIORITY_DEFAULT_REFRESH_RATE:
                    return "PRIORITY_DEFAULT_REFRESH_RATE";
                case PRIORITY_FLICKER:
                    return "PRIORITY_FLICKER";
                case PRIORITY_FLICKER_REFRESH_RATE:
                    return "PRIORITY_FLICKER_REFRESH_RATE";
                case PRIORITY_FLICKER_REFRESH_RATE_SWITCH:
                    return "PRIORITY_FLICKER_REFRESH_RATE_SWITCH";
                case PRIORITY_USER_SETTING_MIN_REFRESH_RATE:
                    return "PRIORITY_USER_SETTING_MIN_REFRESH_RATE";
                case PRIORITY_APP_REQUEST_MAX_REFRESH_RATE:
                    return "PRIORITY_APP_REQUEST_MAX_REFRESH_RATE";
                case PRIORITY_APP_REQUEST_REFRESH_RATE:
                    return "PRIORITY_APP_REQUEST_REFRESH_RATE";
                case PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE:
                    return "PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE";
                case PRIORITY_APP_REQUEST_SIZE:
                    return "PRIORITY_APP_REQUEST_SIZE";
                case PRIORITY_USER_SETTING_PEAK_REFRESH_RATE:
@@ -1025,7 +1088,9 @@ public class DisplayModeDirector {
            return "Vote{"
                + "width=" + width + ", height=" + height
                + ", minRefreshRate=" + refreshRateRange.min
                + ", maxRefreshRate=" + refreshRateRange.max + "}";
                + ", maxRefreshRate=" + refreshRateRange.max
                + ", disableRefreshRateSwitching=" + disableRefreshRateSwitching
                + ", baseModeRefreshRate=" + baseModeRefreshRate + "}";
        }
    }

@@ -1209,21 +1274,22 @@ public class DisplayModeDirector {
                return;
            }

            final Vote refreshRateVote;
            final Vote baseModeRefreshRateVote;
            final Vote sizeVote;
            if (requestedMode != null) {
                mAppRequestedModeByDisplay.put(displayId, requestedMode);
                float refreshRate = requestedMode.getRefreshRate();
                refreshRateVote = Vote.forRefreshRates(refreshRate, refreshRate);
                baseModeRefreshRateVote =
                        Vote.forBaseModeRefreshRate(requestedMode.getRefreshRate());
                sizeVote = Vote.forSize(requestedMode.getPhysicalWidth(),
                        requestedMode.getPhysicalHeight());
            } else {
                mAppRequestedModeByDisplay.remove(displayId);
                refreshRateVote = null;
                baseModeRefreshRateVote = null;
                sizeVote = null;
            }

            updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, refreshRateVote);
            updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
                    baseModeRefreshRateVote);
            updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_SIZE, sizeVote);
        }

@@ -1525,7 +1591,8 @@ public class DisplayModeDirector {
                updateSensorStatus();
                if (!changeable) {
                    // Revoke previous vote from BrightnessObserver
                    updateVoteLocked(Vote.PRIORITY_FLICKER, null);
                    updateVoteLocked(Vote.PRIORITY_FLICKER_REFRESH_RATE, null);
                    updateVoteLocked(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, null);
                }
            }
        }
@@ -1773,7 +1840,8 @@ public class DisplayModeDirector {
            return false;
        }
        private void onBrightnessChangedLocked() {
            Vote vote = null;
            Vote refreshRateVote = null;
            Vote refreshRateSwitchingVote = null;

            if (mBrightness < 0) {
                // Either the setting isn't available or we shouldn't be observing yet anyways.
@@ -1783,20 +1851,25 @@ public class DisplayModeDirector {

            boolean insideLowZone = hasValidLowZone() && isInsideLowZone(mBrightness, mAmbientLux);
            if (insideLowZone) {
                vote = Vote.forRefreshRates(mRefreshRateInLowZone, mRefreshRateInLowZone);
                refreshRateVote =
                        Vote.forRefreshRates(mRefreshRateInLowZone, mRefreshRateInLowZone);
                refreshRateSwitchingVote = Vote.forDisableRefreshRateSwitching();
            }

            boolean insideHighZone = hasValidHighZone()
                    && isInsideHighZone(mBrightness, mAmbientLux);
            if (insideHighZone) {
                vote = Vote.forRefreshRates(mRefreshRateInHighZone, mRefreshRateInHighZone);
                refreshRateVote =
                        Vote.forRefreshRates(mRefreshRateInHighZone, mRefreshRateInHighZone);
                refreshRateSwitchingVote = Vote.forDisableRefreshRateSwitching();
            }

            if (mLoggingEnabled) {
                Slog.d(TAG, "Display brightness " + mBrightness + ", ambient lux " +  mAmbientLux
                        + ", Vote " + vote);
                        + ", Vote " + refreshRateVote);
            }
            updateVoteLocked(Vote.PRIORITY_FLICKER, vote);
            updateVoteLocked(Vote.PRIORITY_FLICKER_REFRESH_RATE, refreshRateVote);
            updateVoteLocked(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, refreshRateSwitchingVote);
        }

        private boolean hasValidLowZone() {
+15 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;

import android.util.ArraySet;
import android.view.Display;
import android.view.Display.Mode;
import android.view.DisplayInfo;

@@ -137,6 +138,19 @@ class RefreshRatePolicy {
        if (mHighRefreshRateDenylist.isDenylisted(packageName)) {
            return mLowRefreshRateMode.getRefreshRate();
        }

        final int preferredModeId = getPreferredModeId(w);
        if (preferredModeId > 0) {
            DisplayInfo info = w.getDisplayInfo();
            if (info != null) {
                for (Display.Mode mode : info.supportedModes) {
                    if (preferredModeId == mode.getModeId()) {
                        return mode.getRefreshRate();
                    }
                }
            }
        }

        return 0;
    }

@@ -147,7 +161,7 @@ class RefreshRatePolicy {
            return 0;
        }

        // If the app set a preferredDisplayModeId, we ignore the max preferred refresh rate
        // If app requests a certain refresh rate or mode, don't override it.
        if (w.mAttrs.preferredDisplayModeId != 0) {
            return 0;
        }
+8 −7
Original line number Diff line number Diff line
@@ -751,11 +751,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
    int mFrameRateSelectionPriority = RefreshRatePolicy.LAYER_PRIORITY_UNSET;

    /**
     * This is the frame rate which is passed to SurfaceFlinger if the window is part of the
     * high refresh rate deny list. The variable is cached, so we do not send too many updates to
     * SF.
     * This is the frame rate which is passed to SurfaceFlinger if the window set a
     * preferredDisplayModeId or is part of the high refresh rate deny list.
     * The variable is cached, so we do not send too many updates to SF.
     */
    float mDenyListFrameRate = 0f;
    float mAppPreferredFrameRate = 0f;

    static final int BLAST_TIMEOUT_DURATION = 5000; /* milliseconds */

@@ -5416,10 +5416,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
        }

        final float refreshRate = refreshRatePolicy.getPreferredRefreshRate(this);
        if (mDenyListFrameRate != refreshRate) {
            mDenyListFrameRate = refreshRate;
        if (mAppPreferredFrameRate != refreshRate) {
            mAppPreferredFrameRate = refreshRate;
            getPendingTransaction().setFrameRate(
                    mSurfaceControl, mDenyListFrameRate, Surface.FRAME_RATE_COMPATIBILITY_EXACT);
                    mSurfaceControl, mAppPreferredFrameRate,
                    Surface.FRAME_RATE_COMPATIBILITY_EXACT, Surface.CHANGE_FRAME_RATE_ALWAYS);
        }
    }

+395 −66

File changed.

Preview size limit exceeded, changes collapsed.

+24 −23

File changed.

Preview size limit exceeded, changes collapsed.

Loading