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

Commit 05ceb414 authored by petsjonkin's avatar petsjonkin
Browse files

Smooth display should also limit physical refreshRate

Bug: b/332413475
Test: atest SettingsObserverTest
Change-Id: Id4040de44978e0efaa47a37a609c7dd1756144f7
parent e2b92673
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -154,6 +154,11 @@ public class DisplayManagerFlags {
            Flags::useFusionProxSensor
    );

    private final FlagState mPeakRefreshRatePhysicalLimit = new FlagState(
            Flags.FLAG_ENABLE_PEAK_REFRESH_RATE_PHYSICAL_LIMIT,
            Flags::enablePeakRefreshRatePhysicalLimit
    );

    /**
     * @return {@code true} if 'port' is allowed in display layout configuration file.
     */
@@ -312,6 +317,10 @@ public class DisplayManagerFlags {
        return mUseFusionProxSensor.getName();
    }

    public boolean isPeakRefreshRatePhysicalLimitEnabled() {
        return mPeakRefreshRatePhysicalLimit.isEnabled();
    }

    /**
     * dumps all flagstates
     * @param pw printWriter
@@ -343,6 +352,7 @@ public class DisplayManagerFlags {
        pw.println(" " + mRefactorDisplayPowerController);
        pw.println(" " + mResolutionBackupRestore);
        pw.println(" " + mUseFusionProxSensor);
        pw.println(" " + mPeakRefreshRatePhysicalLimit);
    }

    private static class FlagState {
+11 −0
Original line number Diff line number Diff line
@@ -244,3 +244,14 @@ flag {
    bug: "306203895"
    is_fixed_read_only: true
}

flag {
    name: "enable_peak_refresh_rate_physical_limit"
    namespace: "display_manager"
    description: "Flag for adding physical refresh rate limit if smooth display setting is on "
    bug: "332413475"
    is_fixed_read_only: true
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+12 −2
Original line number Diff line number Diff line
@@ -940,6 +940,7 @@ public class DisplayModeDirector {
                Settings.Secure.getUriFor(Settings.Secure.MATCH_CONTENT_FRAME_RATE);

        private final boolean mVsynLowPowerVoteEnabled;
        private final boolean mPeakRefreshRatePhysicalLimitEnabled;

        private final Context mContext;
        private float mDefaultPeakRefreshRate;
@@ -950,6 +951,7 @@ public class DisplayModeDirector {
            super(handler);
            mContext = context;
            mVsynLowPowerVoteEnabled = flags.isVsyncLowPowerVoteEnabled();
            mPeakRefreshRatePhysicalLimitEnabled = flags.isPeakRefreshRatePhysicalLimitEnabled();
            // We don't want to load from the DeviceConfig while constructing since this leads to
            // a spike in the latency of DisplayManagerService startup. This happens because
            // reading from the DeviceConfig is an intensive IO operation and having it in the
@@ -1127,11 +1129,19 @@ public class DisplayModeDirector {
            // used to predict if we're going to be doing frequent refresh rate switching, and if
            // so, enable the brightness observer. The logic here is more complicated and fragile
            // than necessary, and we should improve it. See b/156304339 for more info.
            if (mPeakRefreshRatePhysicalLimitEnabled) {
                Vote peakVote = peakRefreshRate == 0f
                        ? null
                        : Vote.forPhysicalRefreshRates(0f,
                                Math.max(minRefreshRate, peakRefreshRate));
                mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE,
                        peakVote);
            }
            Vote peakRenderVote = peakRefreshRate == 0f
                    ? null
                    : Vote.forRenderFrameRates(0f, Math.max(minRefreshRate, peakRefreshRate));
            mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE,
                    peakVote);
                    peakRenderVote);
            mVotesStorage.updateVote(displayId, Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
                    Vote.forRenderFrameRates(minRefreshRate, Float.POSITIVE_INFINITY));
            Vote defaultVote =
+19 −13
Original line number Diff line number Diff line
@@ -76,46 +76,52 @@ interface Vote {

    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)]
    int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 8;
    // PRIORITY_USER_SETTING_PEAK_REFRESH_RATE restricts physical refresh rate to
    // [0, max(PEAK, MIN)], depending on user settings peakRR/minRR values
    int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 8;

    // PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE has a higher priority than
    // PRIORITY_USER_SETTING_PEAK_REFRESH_RATE and will limit render rate to [0, max(PEAK, MIN)]
    // in case physical refresh rate vote is discarded (due to other high priority votes),
    // render rate vote can still apply
    int PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE = 9;

    // Restrict all displays to 60Hz when external display is connected. It votes [59Hz, 61Hz].
    int PRIORITY_SYNCHRONIZED_REFRESH_RATE = 9;
    int PRIORITY_SYNCHRONIZED_REFRESH_RATE = 10;

    // Restrict displays max available resolution and refresh rates. It votes [0, LIMIT]
    int PRIORITY_LIMIT_MODE = 10;
    int PRIORITY_LIMIT_MODE = 11;

    // 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
    int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 11;
    int PRIORITY_AUTH_OPTIMIZER_RENDER_FRAME_RATE = 12;

    // For concurrent displays we want to limit refresh rate on all displays
    int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 12;
    int PRIORITY_LAYOUT_LIMITED_FRAME_RATE = 13;

    // For internal application to limit display modes to specific ids
    int PRIORITY_SYSTEM_REQUESTED_MODES = 13;
    int PRIORITY_SYSTEM_REQUESTED_MODES = 14;

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

    // 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.
    int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 15;
    int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 16;

    // Force display to [0, 60HZ] if skin temperature is at or above CRITICAL.
    int PRIORITY_SKIN_TEMPERATURE = 16;
    int PRIORITY_SKIN_TEMPERATURE = 17;

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

    // 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.
    int PRIORITY_UDFPS = 18;
    int PRIORITY_UDFPS = 19;

    // 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.
+0 −56
Original line number Diff line number Diff line
@@ -78,7 +78,6 @@ import android.view.DisplayInfo;
import android.view.SurfaceControl;
import android.view.SurfaceControl.IdleScreenRefreshRateConfig;
import android.view.SurfaceControl.RefreshRateRange;
import android.view.SurfaceControl.RefreshRateRanges;

import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
@@ -843,61 +842,6 @@ public class DisplayModeDirectorTest {
        assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(expectedAppRequestedRefreshRate);
    }

    void verifySpecsWithRefreshRateSettings(DisplayModeDirector director, float minFps,
            float peakFps, float defaultFps, RefreshRateRanges primary,
            RefreshRateRanges appRequest) {
        DesiredDisplayModeSpecs specs = director.getDesiredDisplayModeSpecsWithInjectedFpsSettings(
                minFps, peakFps, defaultFps);
        assertThat(specs.primary).isEqualTo(primary);
        assertThat(specs.appRequest).isEqualTo(appRequest);
    }

    @Test
    public void testSpecsFromRefreshRateSettings() {
        // Confirm that, with varying settings for min, peak, and default refresh rate,
        // DesiredDisplayModeSpecs is calculated correctly.
        float[] refreshRates = {30.f, 60.f, 90.f, 120.f, 150.f};
        DisplayModeDirector director =
                createDirectorFromRefreshRateArray(refreshRates, /*baseModeId=*/0);

        float inf = Float.POSITIVE_INFINITY;
        RefreshRateRange rangeAll = new RefreshRateRange(0, inf);
        RefreshRateRange range0to60 = new RefreshRateRange(0, 60);
        RefreshRateRange range0to90 = new RefreshRateRange(0, 90);
        RefreshRateRange range0to120 = new RefreshRateRange(0, 120);
        RefreshRateRange range60to90 = new RefreshRateRange(60, 90);
        RefreshRateRange range90to90 = new RefreshRateRange(90, 90);
        RefreshRateRange range90to120 = new RefreshRateRange(90, 120);
        RefreshRateRange range60toInf = new RefreshRateRange(60, inf);
        RefreshRateRange range90toInf = new RefreshRateRange(90, inf);

        RefreshRateRanges frameRateAll = new RefreshRateRanges(rangeAll, rangeAll);
        RefreshRateRanges frameRate90toInf = new RefreshRateRanges(range90toInf, range90toInf);
        RefreshRateRanges frameRate0to60 = new RefreshRateRanges(rangeAll, range0to60);
        RefreshRateRanges frameRate0to90 = new RefreshRateRanges(rangeAll, range0to90);
        RefreshRateRanges frameRate0to120 = new RefreshRateRanges(rangeAll, range0to120);
        RefreshRateRanges frameRate60to90 = new RefreshRateRanges(range60toInf, range60to90);
        RefreshRateRanges frameRate90to90 = new RefreshRateRanges(range90toInf, range90to90);
        RefreshRateRanges frameRate90to120 = new RefreshRateRanges(range90toInf, range90to120);

        verifySpecsWithRefreshRateSettings(director, 0, 0, 0, frameRateAll, frameRateAll);
        verifySpecsWithRefreshRateSettings(director, 0, 0, 90, frameRate0to90, frameRateAll);
        verifySpecsWithRefreshRateSettings(director, 0, 90, 0, frameRate0to90, frameRate0to90);
        verifySpecsWithRefreshRateSettings(director, 0, 90, 60, frameRate0to60, frameRate0to90);
        verifySpecsWithRefreshRateSettings(director, 0, 90, 120, frameRate0to90,
                frameRate0to90);
        verifySpecsWithRefreshRateSettings(director, 90, 0, 0, frameRate90toInf, frameRateAll);
        verifySpecsWithRefreshRateSettings(director, 90, 0, 120, frameRate90to120,
                frameRateAll);
        verifySpecsWithRefreshRateSettings(director, 90, 0, 60, frameRate90toInf, frameRateAll);
        verifySpecsWithRefreshRateSettings(director, 90, 120, 0, frameRate90to120,
                frameRate0to120);
        verifySpecsWithRefreshRateSettings(director, 90, 60, 0, frameRate90to90,
                frameRate0to90);
        verifySpecsWithRefreshRateSettings(director, 60, 120, 90, frameRate60to90,
                frameRate0to120);
    }

    void verifyBrightnessObserverCall(DisplayModeDirector director, float minFps, float peakFps,
            float defaultFps, float brightnessObserverMin, float brightnessObserverMax) {
        BrightnessObserver brightnessObserver = mock(BrightnessObserver.class);
Loading