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

Commit cdd7a5c0 authored by petsjonkin's avatar petsjonkin Committed by Oleg Petšjonkin
Browse files

Do not allow app to change resolution on ext. display

Bug: b/396630700
Test: atest AppRequestObserverTest
Flag: EXEMPT simple bugfix
Change-Id: Iee1e3b69f39f0207dc8e16900c84657eed324427
parent 83062163
Loading
Loading
Loading
Loading
+20 −9
Original line number Diff line number Diff line
@@ -156,6 +156,8 @@ public class DisplayModeDirector {
    private SparseArray<Display.Mode> mDefaultModeByDisplay;
    // a map from display id to display device config
    private SparseArray<DisplayDeviceConfig> mDisplayDeviceConfigByDisplay = new SparseArray<>();
    // set containing connected external display ids
    private final Set<Integer> mExternalDisplaysConnected = new HashSet<>();

    private SparseBooleanArray mHasArrSupport;

@@ -425,7 +427,7 @@ public class DisplayModeDirector {
            // Some external displays physical refresh rate modes are slightly above 60hz.
            // SurfaceFlinger will not enable these display modes unless it is configured to allow
            // render rate at least at this frame rate.
            if (mDisplayObserver.isExternalDisplayLocked(displayId)) {
            if (isExternalDisplayLocked(displayId)) {
                primarySummary.maxRenderFrameRate = Math.max(baseMode.getRefreshRate(),
                        primarySummary.maxRenderFrameRate);
                appRequestSummary.maxRenderFrameRate = Math.max(baseMode.getRefreshRate(),
@@ -653,6 +655,10 @@ public class DisplayModeDirector {
        }
    }

    boolean isExternalDisplayLocked(int displayId) {
        return mExternalDisplaysConnected.contains(displayId);
    }

    private static String switchingTypeToString(@DisplayManager.SwitchingType int type) {
        switch (type) {
            case DisplayManager.SWITCHING_TYPE_NONE:
@@ -693,6 +699,11 @@ public class DisplayModeDirector {
        mVotesStorage.injectVotesByDisplay(votesByDisplay);
    }

    @VisibleForTesting
    void addExternalDisplayId(int externalDisplayId) {
        mExternalDisplaysConnected.add(externalDisplayId);
    }

    @VisibleForTesting
    void injectBrightnessObserver(BrightnessObserver brightnessObserver) {
        mBrightnessObserver = brightnessObserver;
@@ -1210,7 +1221,7 @@ public class DisplayModeDirector {
        @GuardedBy("mLock")
        private void updateRefreshRateSettingLocked(float minRefreshRate, float peakRefreshRate,
                float defaultRefreshRate, int displayId) {
            if (mDisplayObserver.isExternalDisplayLocked(displayId)) {
            if (isExternalDisplayLocked(displayId)) {
                if (mLoggingEnabled) {
                    Slog.d(TAG, "skip updateRefreshRateSettingLocked for external display "
                            + displayId);
@@ -1309,21 +1320,26 @@ public class DisplayModeDirector {
        public void setAppRequest(int displayId, int modeId, float requestedRefreshRate,
                float requestedMinRefreshRateRange, float requestedMaxRefreshRateRange) {
            Display.Mode requestedMode;
            boolean isExternalDisplay;
            synchronized (mLock) {
                requestedMode = findModeLocked(displayId, modeId, requestedRefreshRate);
                isExternalDisplay = isExternalDisplayLocked(displayId);
            }

            Vote frameRateVote = getFrameRateVote(
                    requestedMinRefreshRateRange, requestedMaxRefreshRateRange);
            Vote baseModeRefreshRateVote = getBaseModeVote(requestedMode, requestedRefreshRate);
            Vote sizeVote = getSizeVote(requestedMode);

            mVotesStorage.updateVote(displayId, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE,
                    frameRateVote);
            mVotesStorage.updateVote(displayId, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
                    baseModeRefreshRateVote);

            if (!isExternalDisplay) {
                Vote sizeVote = getSizeVote(requestedMode);
                mVotesStorage.updateVote(displayId, Vote.PRIORITY_APP_REQUEST_SIZE, sizeVote);
            }
        }

        private Display.Mode findModeLocked(int displayId, int modeId, float requestedRefreshRate) {
            Display.Mode mode = null;
@@ -1420,7 +1436,6 @@ public class DisplayModeDirector {
        private int mExternalDisplayPeakHeight;
        private int mExternalDisplayPeakRefreshRate;
        private final boolean mRefreshRateSynchronizationEnabled;
        private final Set<Integer> mExternalDisplaysConnected = new HashSet<>();

        DisplayObserver(Context context, Handler handler, VotesStorage votesStorage,
                Injector injector) {
@@ -1541,10 +1556,6 @@ public class DisplayModeDirector {
            }
        }

        boolean isExternalDisplayLocked(int displayId) {
            return mExternalDisplaysConnected.contains(displayId);
        }

        @Nullable
        private DisplayInfo getDisplayInfo(int displayId) {
            DisplayInfo info = new DisplayInfo();
+33 −0
Original line number Diff line number Diff line
@@ -89,6 +89,39 @@ class AppRequestObserverTest {
        assertThat(renderRateVote).isEqualTo(testCase.expectedRenderRateVote)
    }

    @Test
    fun testAppRequestVote_externalDisplay() {
        val displayModeDirector = DisplayModeDirector(
            context, testHandler, mockInjector, mockFlags, mockDisplayDeviceConfigProvider)
        val modes = arrayOf(
            Display.Mode(1, 1000, 1000, 60f),
            Display.Mode(2, 1000, 1000, 90f),
        )

        displayModeDirector.injectAppSupportedModesByDisplay(
            SparseArray<Array<Display.Mode>>().apply {
                append(Display.DEFAULT_DISPLAY, modes)
            })
        displayModeDirector.injectDefaultModeByDisplay(SparseArray<Display.Mode>().apply {
            append(Display.DEFAULT_DISPLAY, modes[0])
        })
        displayModeDirector.addExternalDisplayId(Display.DEFAULT_DISPLAY)

        displayModeDirector.appRequestObserver.setAppRequest(Display.DEFAULT_DISPLAY, 1, 0f, 0f, 0f)

        val baseModeVote = displayModeDirector.getVote(Display.DEFAULT_DISPLAY,
            Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE)
        assertThat(baseModeVote).isEqualTo(BaseModeRefreshRateVote(60f))

        val sizeVote = displayModeDirector.getVote(Display.DEFAULT_DISPLAY,
            Vote.PRIORITY_APP_REQUEST_SIZE)
        assertThat(sizeVote).isNull()

        val renderRateVote = displayModeDirector.getVote(Display.DEFAULT_DISPLAY,
            Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE)
        assertThat(renderRateVote).isNull()
    }

    enum class AppRequestTestCase(
        val ignoreRefreshRateRequest: Boolean,
        val modeId: Int,