From 1821d25d39b683efd8e951ff62058908f1bc355e Mon Sep 17 00:00:00 2001 From: Oleg Blinnikov Date: Mon, 22 Jul 2024 14:17:17 +0000 Subject: [PATCH] External display mode limit flag in settings Use external display mode limit flag and override for the flag in the settings to allow selection of any resolutions with the refresh rate around 60 Change-Id: I180ba97eb9dfa14a386a7517f29504d369268563 Bug: 351831642 Flag: com.android.settings.flags.resolution_and_enable_connected_display_setting Test: atest ResolutionPreferenceFragmentTest --- .../ExternalDisplaySettingsConfiguration.java | 9 +++ .../display/ResolutionPreferenceFragment.java | 21 ++++++- .../display/ExternalDisplayTestBase.java | 1 + .../ResolutionPreferenceFragmentTest.java | 63 ++++++++++++++++--- 4 files changed, 83 insertions(+), 11 deletions(-) diff --git a/src/com/android/settings/connecteddevice/display/ExternalDisplaySettingsConfiguration.java b/src/com/android/settings/connecteddevice/display/ExternalDisplaySettingsConfiguration.java index 89d464c9a4e..c9ea8ae0a04 100644 --- a/src/com/android/settings/connecteddevice/display/ExternalDisplaySettingsConfiguration.java +++ b/src/com/android/settings/connecteddevice/display/ExternalDisplaySettingsConfiguration.java @@ -23,6 +23,8 @@ import static android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_CONNECT import static android.hardware.display.DisplayManager.EVENT_FLAG_DISPLAY_REMOVED; import static android.view.Display.INVALID_DISPLAY; +import static com.android.server.display.feature.flags.Flags.enableModeLimitForExternalDisplay; + import android.content.Context; import android.hardware.display.DisplayManager; import android.hardware.display.DisplayManagerGlobal; @@ -271,6 +273,13 @@ public class ExternalDisplaySettingsConfiguration { public void setUserPreferredDisplayMode(int displayId, @NonNull Mode mode) { DisplayManagerGlobal.getInstance().setUserPreferredDisplayMode(displayId, mode); } + + /** + * @return true if the display mode limit flag enabled. + */ + public boolean isModeLimitForExternalDisplayEnabled() { + return enableModeLimitForExternalDisplay(); + } } public abstract static class DisplayListener implements DisplayManager.DisplayListener { diff --git a/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragment.java b/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragment.java index 10314cb1e21..db81be89a42 100644 --- a/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragment.java +++ b/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragment.java @@ -52,7 +52,7 @@ import java.util.ArrayList; import java.util.HashSet; public class ResolutionPreferenceFragment extends SettingsPreferenceFragmentBase { - private static final String TAG = "ResolutionPreferenceFragment"; + private static final String TAG = "ResolutionPreference"; static final int DEFAULT_LOW_REFRESH_RATE = 60; static final String MORE_OPTIONS_KEY = "more_options"; static final String TOP_OPTIONS_KEY = "top_options"; @@ -60,6 +60,8 @@ public class ResolutionPreferenceFragment extends SettingsPreferenceFragmentBase R.string.external_display_more_options_title; static final int EXTERNAL_DISPLAY_RESOLUTION_SETTINGS_RESOURCE = R.xml.external_display_resolution_settings; + static final String DISPLAY_MODE_LIMIT_OVERRIDE_PROP = "persist.sys.com.android.server.display" + + ".feature.flags.enable_mode_limit_for_external_display-override"; @Nullable private Injector mInjector; @Nullable @@ -323,16 +325,29 @@ public class ResolutionPreferenceFragment extends SettingsPreferenceFragmentBase } } + private boolean isDisplayResolutionLimitEnabled() { + if (mInjector == null) { + return false; + } + var flagOverride = mInjector.getSystemProperty(DISPLAY_MODE_LIMIT_OVERRIDE_PROP); + var isOverrideEnabled = "true".equals(flagOverride); + var isOverrideEnabledOrNotSet = !"false".equals(flagOverride); + return (mInjector.isModeLimitForExternalDisplayEnabled() && isOverrideEnabledOrNotSet) + || isOverrideEnabled; + } + private void updateDisplayModeLimits(@Nullable Context context) { if (context == null) { return; } mExternalDisplayPeakRefreshRate = getResources(context).getInteger( com.android.internal.R.integer.config_externalDisplayPeakRefreshRate); - mExternalDisplayPeakWidth = getResources(context).getInteger( + if (isDisplayResolutionLimitEnabled()) { + mExternalDisplayPeakWidth = getResources(context).getInteger( com.android.internal.R.integer.config_externalDisplayPeakWidth); - mExternalDisplayPeakHeight = getResources(context).getInteger( + mExternalDisplayPeakHeight = getResources(context).getInteger( com.android.internal.R.integer.config_externalDisplayPeakHeight); + } mRefreshRateSynchronizationEnabled = getResources(context).getBoolean( com.android.internal.R.bool.config_refreshRateSynchronizationEnabled); Log.d(TAG, "mExternalDisplayPeakRefreshRate=" + mExternalDisplayPeakRefreshRate); diff --git a/tests/unit/src/com/android/settings/connecteddevice/display/ExternalDisplayTestBase.java b/tests/unit/src/com/android/settings/connecteddevice/display/ExternalDisplayTestBase.java index 60b034288a0..4cba1ef4666 100644 --- a/tests/unit/src/com/android/settings/connecteddevice/display/ExternalDisplayTestBase.java +++ b/tests/unit/src/com/android/settings/connecteddevice/display/ExternalDisplayTestBase.java @@ -87,6 +87,7 @@ public class ExternalDisplayTestBase { doReturn(mHandler).when(mMockedInjector).getHandler(); doReturn("").when(mMockedInjector).getSystemProperty( VIRTUAL_DISPLAY_PACKAGE_NAME_SYSTEM_PROPERTY); + doReturn(true).when(mMockedInjector).isModeLimitForExternalDisplayEnabled(); doAnswer((arg) -> { mListener = arg.getArgument(0); return null; diff --git a/tests/unit/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragmentTest.java b/tests/unit/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragmentTest.java index ee38a1cbae2..c8663622e74 100644 --- a/tests/unit/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragmentTest.java +++ b/tests/unit/src/com/android/settings/connecteddevice/display/ResolutionPreferenceFragmentTest.java @@ -17,6 +17,7 @@ package com.android.settings.connecteddevice.display; import static android.view.Display.INVALID_DISPLAY; +import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.DISPLAY_MODE_LIMIT_OVERRIDE_PROP; import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.EXTERNAL_DISPLAY_RESOLUTION_SETTINGS_RESOURCE; import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.MORE_OPTIONS_KEY; import static com.android.settings.connecteddevice.display.ResolutionPreferenceFragment.TOP_OPTIONS_KEY; @@ -29,6 +30,7 @@ import static org.mockito.Mockito.verify; import android.content.Context; import android.content.res.Resources; +import android.util.Pair; import android.view.View; import android.widget.TextView; @@ -83,18 +85,52 @@ public class ResolutionPreferenceFragmentTest extends ExternalDisplayTestBase { @Test @UiThreadTest - public void testModePreferences() { - mDisplayIdArg = 1; - initFragment(); - mHandler.flush(); - PreferenceCategory topPref = mPreferenceScreen.findPreference(TOP_OPTIONS_KEY); - assertThat(topPref).isNotNull(); - PreferenceCategory morePref = mPreferenceScreen.findPreference(MORE_OPTIONS_KEY); - assertThat(morePref).isNotNull(); + public void testModePreferences_modeLimitFlagIsOn_noOverride() { + doReturn(true).when(mMockedInjector).isModeLimitForExternalDisplayEnabled(); + doReturn(null).when(mMockedInjector).getSystemProperty( + DISPLAY_MODE_LIMIT_OVERRIDE_PROP); + var topAndMorePref = runTestModePreferences(); + PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second; assertThat(topPref.getPreferenceCount()).isEqualTo(3); assertThat(morePref.getPreferenceCount()).isEqualTo(1); } + @Test + @UiThreadTest + public void testModePreferences_noModeLimitFlag_overrideIsTrue() { + doReturn(false).when(mMockedInjector).isModeLimitForExternalDisplayEnabled(); + doReturn("true").when(mMockedInjector).getSystemProperty( + DISPLAY_MODE_LIMIT_OVERRIDE_PROP); + var topAndMorePref = runTestModePreferences(); + PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second; + assertThat(topPref.getPreferenceCount()).isEqualTo(3); + assertThat(morePref.getPreferenceCount()).isEqualTo(1); + } + + @Test + @UiThreadTest + public void testModePreferences_noModeLimitFlag_noOverride() { + doReturn(false).when(mMockedInjector).isModeLimitForExternalDisplayEnabled(); + doReturn(null).when(mMockedInjector).getSystemProperty( + DISPLAY_MODE_LIMIT_OVERRIDE_PROP); + var topAndMorePref = runTestModePreferences(); + PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second; + assertThat(topPref.getPreferenceCount()).isEqualTo(3); + assertThat(morePref.getPreferenceCount()).isEqualTo(2); + } + + @Test + @UiThreadTest + public void testModePreferences_modeLimitFlagIsOn_butOverrideIsFalse() { + doReturn(true).when(mMockedInjector).isModeLimitForExternalDisplayEnabled(); + doReturn("false").when(mMockedInjector).getSystemProperty( + DISPLAY_MODE_LIMIT_OVERRIDE_PROP); + var topAndMorePref = runTestModePreferences(); + PreferenceCategory topPref = topAndMorePref.first, morePref = topAndMorePref.second; + assertThat(topPref.getPreferenceCount()).isEqualTo(3); + assertThat(morePref.getPreferenceCount()).isEqualTo(2); + } + @Test @UiThreadTest public void testModeChange() { @@ -109,6 +145,17 @@ public class ResolutionPreferenceFragmentTest extends ExternalDisplayTestBase { verify(mMockedInjector).setUserPreferredDisplayMode(mDisplayIdArg, mode); } + private Pair runTestModePreferences() { + mDisplayIdArg = 1; + initFragment(); + mHandler.flush(); + PreferenceCategory topPref = mPreferenceScreen.findPreference(TOP_OPTIONS_KEY); + assertThat(topPref).isNotNull(); + PreferenceCategory morePref = mPreferenceScreen.findPreference(MORE_OPTIONS_KEY); + assertThat(morePref).isNotNull(); + return new Pair<>(topPref, morePref); + } + private void initFragment() { if (mFragment != null) { return;