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

Commit c5b123ad authored by Oleg Blinnikov's avatar Oleg Blinnikov
Browse files

Vote for userPreferredMode

Previously userPreferredMode was sent via defaultMode
to DisplayModeDirector. Now DisplayModeDirector needs
a way to understand whether the mode is the default
or userPreferredMode. This is important for creating
the userPreferredMode vote only for user preferred and
not the default mode.

With this CL, DisplayModeDirector creates the
user preferred mode vote with a predefined priority.

Change-Id: I0d24391f1c9938e3e49ee219bb040e4ade7794e0
Test: atest com.android.server.display.mode
Bug: 242093547
parent 5226ffc8
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -51,6 +51,10 @@ public class DisplayManagerFlags {
            Flags.FLAG_ENABLE_DISPLAY_RESOLUTION_RANGE_VOTING,
            Flags::enableDisplayResolutionRangeVoting);

    private final FlagState mUserPreferredModeVoteState = new FlagState(
            Flags.FLAG_ENABLE_USER_PREFERRED_MODE_VOTE,
            Flags::enableUserPreferredModeVote);

    /** Returns whether connected display management is enabled or not. */
    public boolean isConnectedDisplayManagementEnabled() {
        return mConnectedDisplayManagementFlagState.isEnabled();
@@ -77,6 +81,14 @@ public class DisplayManagerFlags {
        return mDisplayResolutionRangeVotingState.isEnabled();
    }

    /**
     * @return Whether user preferred mode is added as a vote in
     *      {@link com.android.server.display.mode.DisplayModeDirector}
     */
    public boolean isUserPreferredModeVoteEnabled() {
        return mUserPreferredModeVoteState.isEnabled();
    }

    private static class FlagState {

        private final String mName;
+8 −0
Original line number Diff line number Diff line
@@ -41,3 +41,11 @@ flag {
    bug: "299297058"
    is_fixed_read_only: true
}

flag {
    name: "enable_user_preferred_mode_vote"
    namespace: "display_manager"
    description: "Feature flag to use voting for UserPreferredMode for display"
    bug: "297018612"
    is_fixed_read_only: true
}
+48 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ package com.android.server.display.mode;
import static android.hardware.display.DisplayManager.DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED;
import static android.hardware.display.DisplayManagerInternal.REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE;
import static android.os.PowerManager.BRIGHTNESS_INVALID_FLOAT;
import static android.view.Display.Mode.INVALID_MODE_ID;

import android.annotation.IntegerRes;
import android.annotation.NonNull;
@@ -157,6 +158,11 @@ public class DisplayModeDirector {
     */
    private final boolean mIsDisplayResolutionRangeVotingEnabled;

    /**
     * Whether user preferred mode voting feature is enabled.
     */
    private final boolean mIsUserPreferredModeVoteEnabled;

    public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler,
            @NonNull DisplayManagerFlags displayManagerFlags) {
        this(context, handler, new RealInjector(context), displayManagerFlags);
@@ -167,6 +173,7 @@ public class DisplayModeDirector {
            @NonNull DisplayManagerFlags displayManagerFlags) {
        mIsDisplayResolutionRangeVotingEnabled = displayManagerFlags
                .isDisplayResolutionRangeVotingEnabled();
        mIsUserPreferredModeVoteEnabled = displayManagerFlags.isUserPreferredModeVoteEnabled();
        mContext = context;
        mHandler = new DisplayModeDirectorHandler(handler.getLooper());
        mInjector = injector;
@@ -1485,6 +1492,7 @@ public class DisplayModeDirector {
            DisplayInfo displayInfo = getDisplayInfo(displayId);
            updateDisplayModes(displayId, displayInfo);
            updateLayoutLimitedFrameRate(displayId, displayInfo);
            updateUserSettingDisplayPreferredSize(displayInfo);
        }

        @Override
@@ -1494,6 +1502,7 @@ public class DisplayModeDirector {
                mDefaultModeByDisplay.remove(displayId);
            }
            updateLayoutLimitedFrameRate(displayId, null);
            removeUserSettingDisplayPreferredSize(displayId);
        }

        @Override
@@ -1501,6 +1510,7 @@ public class DisplayModeDirector {
            DisplayInfo displayInfo = getDisplayInfo(displayId);
            updateDisplayModes(displayId, displayInfo);
            updateLayoutLimitedFrameRate(displayId, displayInfo);
            updateUserSettingDisplayPreferredSize(displayInfo);
        }

        @Nullable
@@ -1517,6 +1527,44 @@ public class DisplayModeDirector {
            mVotesStorage.updateVote(displayId, Vote.PRIORITY_LAYOUT_LIMITED_FRAME_RATE, vote);
        }

        private void removeUserSettingDisplayPreferredSize(int displayId) {
            if (!mIsUserPreferredModeVoteEnabled) {
                return;
            }
            mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE,
                    null);
        }

        private void updateUserSettingDisplayPreferredSize(@Nullable DisplayInfo info) {
            if (info == null || !mIsUserPreferredModeVoteEnabled) {
                return;
            }

            var preferredMode = findDisplayPreferredMode(info);
            if (preferredMode == null) {
                removeUserSettingDisplayPreferredSize(info.displayId);
                return;
            }

            mVotesStorage.updateVote(info.displayId,
                    Vote.PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE,
                    Vote.forSize(/* width */ preferredMode.getPhysicalWidth(),
                            /* height */ preferredMode.getPhysicalHeight()));
        }

        @Nullable
        private Display.Mode findDisplayPreferredMode(@NonNull DisplayInfo info) {
            if (info.userPreferredModeId == INVALID_MODE_ID) {
                return null;
            }
            for (var mode : info.supportedModes) {
                if (mode.getModeId() == info.userPreferredModeId) {
                    return mode;
                }
            }
            return null;
        }

        private void updateDisplayModes(int displayId, @Nullable DisplayInfo info) {
            if (info == null) {
                return;
+38 −11
Original line number Diff line number Diff line
@@ -18,6 +18,8 @@ package com.android.server.display.mode;

import android.view.SurfaceControl;

import java.util.Objects;

final class Vote {
    // DEFAULT_RENDER_FRAME_RATE votes for render frame rate [0, DEFAULT]. As the lowest
    // priority vote, it's overridden by all other considerations. It acts to set a default
@@ -36,12 +38,15 @@ final class Vote {
    // It votes [minRefreshRate, Float.POSITIVE_INFINITY]
    static final int PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE = 3;

    // User setting preferred display resolution.
    static final int PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE = 4;

    // APP_REQUEST_RENDER_FRAME_RATE_RANGE is used to for internal apps to limit the render
    // frame rate in certain cases, mostly to preserve power.
    // @see android.view.WindowManager.LayoutParams#preferredMinRefreshRate
    // @see android.view.WindowManager.LayoutParams#preferredMaxRefreshRate
    // It votes to [preferredMinRefreshRate, preferredMaxRefreshRate].
    static final int PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE = 4;
    static final int PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE = 5;

    // We split the app request into different priorities in case we can satisfy one desire
    // without the other.
@@ -67,40 +72,41 @@ final class Vote {
    // The preferred refresh rate is set on the main surface of the app outside of
    // DisplayModeDirector.
    // @see com.android.server.wm.WindowState#updateFrameRateSelectionPriorityIfNeeded
    static final int PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE = 5;
    static final int PRIORITY_APP_REQUEST_SIZE = 6;
    static final int PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE = 6;

    static final int PRIORITY_APP_REQUEST_SIZE = 7;

    // SETTING_PEAK_RENDER_FRAME_RATE has a high priority and will restrict the bounds of the
    // rest of low priority voters. It votes [0, max(PEAK, MIN)]
    static final int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 7;
    static final int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 8;

    // To avoid delay in switching between 60HZ -> 90HZ when activating LHBM, set refresh
    // rate to max value (same as for PRIORITY_UDFPS) on lock screen
    static final int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 8;
    static final int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 9;

    // For concurrent displays we want to limit refresh rate on all displays
    static final int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 9;
    static final int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 10;

    // LOW_POWER_MODE force the render frame rate to [0, 60HZ] if
    // Settings.Global.LOW_POWER_MODE is on.
    static final int PRIORITY_LOW_POWER_MODE = 10;
    static final int PRIORITY_LOW_POWER_MODE = 11;

    // 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.
    static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 11;
    static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 12;

    // Force display to [0, 60HZ] if skin temperature is at or above CRITICAL.
    static final int PRIORITY_SKIN_TEMPERATURE = 12;
    static final int PRIORITY_SKIN_TEMPERATURE = 13;

    // The proximity sensor needs the refresh rate to be locked in order to function, so this is
    // set to a high priority.
    static final int PRIORITY_PROXIMITY = 13;
    static final int PRIORITY_PROXIMITY = 14;

    // 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.
    static final int PRIORITY_UDFPS = 14;
    static final int PRIORITY_UDFPS = 15;

    // 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.
@@ -263,6 +269,8 @@ final class Vote {
                return "PRIORITY_UDFPS";
            case PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE:
                return "PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE";
            case PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE:
                return "PRIORITY_USER_SETTING_DISPLAY_PREFERRED_SIZE";
            case PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE:
                return "PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE";
            case PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE:
@@ -283,4 +291,23 @@ final class Vote {
                + ", disableRefreshRateSwitching: " + disableRefreshRateSwitching
                + ", appRequestBaseModeRefreshRate: "  + appRequestBaseModeRefreshRate + "}";
    }

    @Override
    public int hashCode() {
        return Objects.hash(minWidth, minHeight, width, height, refreshRateRanges,
                disableRefreshRateSwitching, appRequestBaseModeRefreshRate);
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof Vote)) return false;
        final var vote = (Vote) o;
        return  minWidth == vote.minWidth && minHeight == vote.minHeight
                && width == vote.width && height == vote.height
                && disableRefreshRateSwitching == vote.disableRefreshRateSwitching
                && Float.compare(vote.appRequestBaseModeRefreshRate,
                        appRequestBaseModeRefreshRate) == 0
                && refreshRateRanges.equals(vote.refreshRateRanges);
    }
}
+9 −3
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ class VotesStorage {
                    + ", vote=" + vote);
            return;
        }
        boolean changed = false;
        SparseArray<Vote> votes;
        synchronized (mStorageLock) {
            if (mVotesByDisplay.contains(displayId)) {
@@ -98,17 +99,22 @@ class VotesStorage {
                votes = new SparseArray<>();
                mVotesByDisplay.put(displayId, votes);
            }
            if (vote != null) {
            var currentVote = votes.get(priority);
            if (vote != null && !vote.equals(currentVote)) {
                votes.put(priority, vote);
            } else {
                changed = true;
            } else if (vote == null && currentVote != null) {
                votes.remove(priority);
                changed = true;
            }
        }
        if (mLoggingEnabled) {
            Slog.i(TAG, "Updated votes for display=" + displayId + " votes=" + votes);
        }
        if (changed) {
            mListener.onChanged();
        }
    }

    /** dump class values, for debugging */
    void dump(@NonNull PrintWriter pw) {
Loading