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
This commit is contained in:
Oleg Blinnikov
2024-07-22 14:17:17 +00:00
parent c56c2e0019
commit 1821d25d39
4 changed files with 83 additions and 11 deletions

View File

@@ -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 {

View File

@@ -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);

View File

@@ -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;

View File

@@ -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<PreferenceCategory, PreferenceCategory> 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;