diff options
9 files changed, 457 insertions, 53 deletions
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index 561f7982c1de..c8ab150cbdfe 100644 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -4668,22 +4668,16 @@ public final class Settings { "display_color_mode_vendor_hint"; /** - * The user selected min refresh rate in frames per second. - * - * If this isn't set, 0 will be used. + * Whether or not the peak refresh rate should be forced. 0=no, 1=yes * @hide */ - @Readable - public static final String MIN_REFRESH_RATE = "min_refresh_rate"; + public static final String FORCE_PEAK_REFRESH_RATE = "force_peak_refresh_rate"; /** - * The user selected peak refresh rate in frames per second. - * - * If this isn't set, the system falls back to a device specific default. + * Whether or not the peak refresh rate should be used for some content. 0=no, 1=yes * @hide */ - @Readable - public static final String PEAK_REFRESH_RATE = "peak_refresh_rate"; + public static final String SMOOTH_DISPLAY = "smooth_display"; /** * The amount of time in milliseconds before the device goes to sleep or begins diff --git a/core/java/com/android/internal/display/RefreshRateSettingsUtils.java b/core/java/com/android/internal/display/RefreshRateSettingsUtils.java new file mode 100644 index 000000000000..39d8380c7e95 --- /dev/null +++ b/core/java/com/android/internal/display/RefreshRateSettingsUtils.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.internal.display; + +import android.content.ContentResolver; +import android.content.Context; +import android.hardware.display.DisplayManager; +import android.provider.Settings; +import android.util.Log; +import android.view.Display; + +/** + * Constants and utility methods for refresh rate settings. + */ +public class RefreshRateSettingsUtils { + + private static final String TAG = "RefreshRateSettingsUtils"; + + public static final float DEFAULT_REFRESH_RATE = 60f; + + /** + * Find the highest refresh rate among all the modes of the default display. + * @param context The context + * @return The highest refresh rate + */ + public static float findHighestRefreshRateForDefaultDisplay(Context context) { + final DisplayManager dm = context.getSystemService(DisplayManager.class); + final Display display = dm.getDisplay(Display.DEFAULT_DISPLAY); + + if (display == null) { + Log.w(TAG, "No valid default display device"); + return DEFAULT_REFRESH_RATE; + } + + float maxRefreshRate = DEFAULT_REFRESH_RATE; + for (Display.Mode mode : display.getSupportedModes()) { + if (Math.round(mode.getRefreshRate()) > maxRefreshRate) { + maxRefreshRate = mode.getRefreshRate(); + } + } + return maxRefreshRate; + } + + /** + * Get the min refresh rate which is determined by + * {@link Settings.System.FORCE_PEAK_REFRESH_RATE}. + * @param context The context + * @return The min refresh rate + */ + public static float getMinRefreshRate(Context context) { + final ContentResolver cr = context.getContentResolver(); + int forcePeakRefreshRateSetting = Settings.System.getIntForUser(cr, + Settings.System.FORCE_PEAK_REFRESH_RATE, -1, cr.getUserId()); + return forcePeakRefreshRateSetting == 1 + ? findHighestRefreshRateForDefaultDisplay(context) + : 0; + } + + /** + * Get the peak refresh rate which is determined by {@link Settings.System.SMOOTH_DISPLAY}. + * @param context The context + * @param defaultPeakRefreshRate The refresh rate to return if the setting doesn't have a value + * @return The peak refresh rate + */ + public static float getPeakRefreshRate(Context context, float defaultPeakRefreshRate) { + final ContentResolver cr = context.getContentResolver(); + int smoothDisplaySetting = Settings.System.getIntForUser(cr, + Settings.System.SMOOTH_DISPLAY, -1, cr.getUserId()); + switch (smoothDisplaySetting) { + case 0: + return DEFAULT_REFRESH_RATE; + case 1: + return findHighestRefreshRateForDefaultDisplay(context); + default: + return defaultPeakRefreshRate; + } + } +} diff --git a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java index 6a5535d345db..e4cc9f15aea1 100644 --- a/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java +++ b/packages/SettingsProvider/src/android/provider/settings/backup/SystemSettings.java @@ -100,5 +100,6 @@ public class SystemSettings { Settings.System.CAMERA_FLASH_NOTIFICATION, Settings.System.SCREEN_FLASH_NOTIFICATION, Settings.System.SCREEN_FLASH_NOTIFICATION_COLOR, + Settings.System.SMOOTH_DISPLAY }; } diff --git a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java index 85623b26c589..4b720636c1d4 100644 --- a/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java +++ b/packages/SettingsProvider/src/android/provider/settings/validators/SystemSettingsValidators.java @@ -226,5 +226,6 @@ public class SystemSettingsValidators { VALIDATORS.put(System.CAMERA_FLASH_NOTIFICATION, BOOLEAN_VALIDATOR); VALIDATORS.put(System.SCREEN_FLASH_NOTIFICATION, BOOLEAN_VALIDATOR); VALIDATORS.put(System.SCREEN_FLASH_NOTIFICATION_COLOR, ANY_INTEGER_VALIDATOR); + VALIDATORS.put(System.SMOOTH_DISPLAY, BOOLEAN_VALIDATOR); } } diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java index 284b06b86cb6..d1bd5e661072 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java @@ -34,6 +34,7 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OV import static com.android.internal.accessibility.AccessibilityShortcutController.MAGNIFICATION_CONTROLLER_NAME; import static com.android.internal.accessibility.util.AccessibilityUtils.ACCESSIBILITY_MENU_IN_SYSTEM; +import static com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE; import static com.android.providers.settings.SettingsState.FALLBACK_FILE_SUFFIX; import static com.android.providers.settings.SettingsState.getTypeFromKey; import static com.android.providers.settings.SettingsState.getUserIdFromKey; @@ -3748,7 +3749,7 @@ public class SettingsProvider extends ContentProvider { } private final class UpgradeController { - private static final int SETTINGS_VERSION = 218; + private static final int SETTINGS_VERSION = 219; private final int mUserId; @@ -5673,7 +5674,7 @@ public class SettingsProvider extends ContentProvider { providers.addAll(Arrays.asList(resources.getStringArray(resourceId))); } catch (Resources.NotFoundException e) { Slog.w(LOG_TAG, - "Get default array Cred Provider not found: " + e.toString()); + "Get default array Cred Provider not found: " + e.toString()); } try { final String storedValue = resources.getString(resourceId); @@ -5682,7 +5683,7 @@ public class SettingsProvider extends ContentProvider { } } catch (Resources.NotFoundException e) { Slog.w(LOG_TAG, - "Get default Cred Provider not found: " + e.toString()); + "Get default Cred Provider not found: " + e.toString()); } if (!providers.isEmpty()) { @@ -5731,8 +5732,8 @@ public class SettingsProvider extends ContentProvider { final Setting currentSetting = secureSettings .getSettingLocked(Settings.Secure.CREDENTIAL_SERVICE); if (currentSetting.isNull()) { - final int resourceId = - com.android.internal.R.array.config_defaultCredentialProviderService; + final int resourceId = com.android.internal.R.array + .config_defaultCredentialProviderService; final Resources resources = getContext().getResources(); // If the config has not be defined we might get an exception. final List<String> providers = new ArrayList<>(); @@ -5740,7 +5741,7 @@ public class SettingsProvider extends ContentProvider { providers.addAll(Arrays.asList(resources.getStringArray(resourceId))); } catch (Resources.NotFoundException e) { Slog.w(LOG_TAG, - "Get default array Cred Provider not found: " + e.toString()); + "Get default array Cred Provider not found: " + e.toString()); } if (!providers.isEmpty()) { @@ -5839,6 +5840,47 @@ public class SettingsProvider extends ContentProvider { currentVersion = 218; } + // v218: Convert Smooth Display and Force Peak Refresh Rate to a boolean + if (currentVersion == 218) { + final String peakRefreshRateSettingName = "peak_refresh_rate"; + final String minRefreshRateSettingName = "min_refresh_rate"; + + final SettingsState systemSettings = getSystemSettingsLocked(userId); + final Setting peakRefreshRateSetting = + systemSettings.getSettingLocked(peakRefreshRateSettingName); + final Setting minRefreshRateSetting = + systemSettings.getSettingLocked(minRefreshRateSettingName); + + float peakRefreshRate = DEFAULT_REFRESH_RATE; + float minRefreshRate = 0; + try { + if (!peakRefreshRateSetting.isNull()) { + peakRefreshRate = Float.parseFloat(peakRefreshRateSetting.getValue()); + } + } catch (NumberFormatException e) { + // Do nothing. Overwrite with default value. + } + try { + if (!minRefreshRateSetting.isNull()) { + minRefreshRate = Float.parseFloat(minRefreshRateSetting.getValue()); + } + } catch (NumberFormatException e) { + // Do nothing. Overwrite with default value. + } + + systemSettings.deleteSettingLocked(peakRefreshRateSettingName); + systemSettings.deleteSettingLocked(minRefreshRateSettingName); + + systemSettings.insertSettingLocked(Settings.System.SMOOTH_DISPLAY, + peakRefreshRate > DEFAULT_REFRESH_RATE ? "1" : "0", /* tag= */ null, + /* makeDefault= */ false, SettingsState.SYSTEM_PACKAGE_NAME); + systemSettings.insertSettingLocked(Settings.System.FORCE_PEAK_REFRESH_RATE, + minRefreshRate > 0 ? "1" : "0", /* tag= */ null, + /* makeDefault= */ false, SettingsState.SYSTEM_PACKAGE_NAME); + + currentVersion = 219; + } + // vXXX: Add new settings above this point. if (currentVersion != newVersion) { diff --git a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java index 706666cbebab..36aa2ac74406 100644 --- a/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java +++ b/packages/SettingsProvider/test/src/android/provider/SettingsBackupTest.java @@ -97,8 +97,7 @@ public class SettingsBackupTest { Settings.System.WHEN_TO_MAKE_WIFI_CALLS, // bug? Settings.System.WINDOW_ORIENTATION_LISTENER_LOG, // used for debugging only Settings.System.DESKTOP_MODE, // developer setting for internal prototyping - Settings.System.MIN_REFRESH_RATE, // depends on hardware capabilities - Settings.System.PEAK_REFRESH_RATE, // depends on hardware capabilities + Settings.System.FORCE_PEAK_REFRESH_RATE, // depends on hardware capabilities Settings.System.SCREEN_BRIGHTNESS_FLOAT, Settings.System.SCREEN_AUTO_BRIGHTNESS_ADJ, Settings.System.MULTI_AUDIO_FOCUS_ENABLED // form-factor/OEM specific diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java index 01892945ed17..03b49f088c2f 100644 --- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java @@ -65,6 +65,7 @@ import com.android.internal.R; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.display.BrightnessSynchronizer; +import com.android.internal.display.RefreshRateSettingsUtils; import com.android.internal.os.BackgroundThread; import com.android.server.LocalServices; import com.android.server.display.DisplayDeviceConfig; @@ -1171,7 +1172,7 @@ public class DisplayModeDirector { public static final int PRIORITY_HIGH_BRIGHTNESS_MODE = 2; // SETTING_MIN_RENDER_FRAME_RATE is used to propose a lower bound of the render frame rate. - // It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY] + // It votes [minRefreshRate, Float.POSITIVE_INFINITY] public static final int PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE = 3; // APP_REQUEST_RENDER_FRAME_RATE_RANGE is used to for internal apps to limit the render @@ -1376,10 +1377,10 @@ public class DisplayModeDirector { @VisibleForTesting final class SettingsObserver extends ContentObserver { - private final Uri mPeakRefreshRateSetting = - Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE); - private final Uri mMinRefreshRateSetting = - Settings.System.getUriFor(Settings.System.MIN_REFRESH_RATE); + private final Uri mSmoothDisplaySetting = + Settings.System.getUriFor(Settings.System.SMOOTH_DISPLAY); + private final Uri mForcePeakRefreshRateSetting = + Settings.System.getUriFor(Settings.System.FORCE_PEAK_REFRESH_RATE); private final Uri mLowPowerModeSetting = Settings.Global.getUriFor(Settings.Global.LOW_POWER_MODE); private final Uri mMatchContentFrameRateSetting = @@ -1415,9 +1416,8 @@ public class DisplayModeDirector { public void observe() { final ContentResolver cr = mContext.getContentResolver(); - mInjector.registerPeakRefreshRateObserver(cr, this); - cr.registerContentObserver(mMinRefreshRateSetting, false /*notifyDescendants*/, this, - UserHandle.USER_SYSTEM); + mInjector.registerSmoothDisplayObserver(cr, this); + mInjector.registerForcePeakRefreshRateObserver(cr, this); cr.registerContentObserver(mLowPowerModeSetting, false /*notifyDescendants*/, this, UserHandle.USER_SYSTEM); cr.registerContentObserver(mMatchContentFrameRateSetting, false /*notifyDescendants*/, @@ -1459,8 +1459,8 @@ public class DisplayModeDirector { @Override public void onChange(boolean selfChange, Uri uri, int userId) { synchronized (mLock) { - if (mPeakRefreshRateSetting.equals(uri) - || mMinRefreshRateSetting.equals(uri)) { + if (mSmoothDisplaySetting.equals(uri) + || mForcePeakRefreshRateSetting.equals(uri)) { updateRefreshRateSettingLocked(); } else if (mLowPowerModeSetting.equals(uri)) { updateLowPowerModeSettingLocked(); @@ -1515,12 +1515,9 @@ public class DisplayModeDirector { } private void updateRefreshRateSettingLocked() { - final ContentResolver cr = mContext.getContentResolver(); - float minRefreshRate = Settings.System.getFloatForUser(cr, - Settings.System.MIN_REFRESH_RATE, 0f, cr.getUserId()); - float peakRefreshRate = Settings.System.getFloatForUser(cr, - Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate, cr.getUserId()); - updateRefreshRateSettingLocked(minRefreshRate, peakRefreshRate, mDefaultRefreshRate); + updateRefreshRateSettingLocked(RefreshRateSettingsUtils.getMinRefreshRate(mContext), + RefreshRateSettingsUtils.getPeakRefreshRate(mContext, mDefaultPeakRefreshRate), + mDefaultRefreshRate); } private void updateRefreshRateSettingLocked( @@ -3165,12 +3162,17 @@ public class DisplayModeDirector { } interface Injector { - Uri PEAK_REFRESH_RATE_URI = Settings.System.getUriFor(Settings.System.PEAK_REFRESH_RATE); + Uri SMOOTH_DISPLAY_URI = Settings.System.getUriFor(Settings.System.SMOOTH_DISPLAY); + Uri FORCE_PEAK_REFRESH_RATE_URI = + Settings.System.getUriFor(Settings.System.FORCE_PEAK_REFRESH_RATE); @NonNull DeviceConfigInterface getDeviceConfig(); - void registerPeakRefreshRateObserver(@NonNull ContentResolver cr, + void registerSmoothDisplayObserver(@NonNull ContentResolver cr, + @NonNull ContentObserver observer); + + void registerForcePeakRefreshRateObserver(@NonNull ContentResolver cr, @NonNull ContentObserver observer); void registerDisplayListener(@NonNull DisplayManager.DisplayListener listener, @@ -3205,9 +3207,16 @@ public class DisplayModeDirector { } @Override - public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr, + public void registerSmoothDisplayObserver(@NonNull ContentResolver cr, + @NonNull ContentObserver observer) { + cr.registerContentObserver(SMOOTH_DISPLAY_URI, false /*notifyDescendants*/, + observer, UserHandle.USER_SYSTEM); + } + + @Override + public void registerForcePeakRefreshRateObserver(@NonNull ContentResolver cr, @NonNull ContentObserver observer) { - cr.registerContentObserver(PEAK_REFRESH_RATE_URI, false /*notifyDescendants*/, + cr.registerContentObserver(FORCE_PEAK_REFRESH_RATE_URI, false /*notifyDescendants*/, observer, UserHandle.USER_SYSTEM); } diff --git a/services/tests/mockingservicestests/src/com/android/server/display/RefreshRateSettingsUtilsTest.java b/services/tests/mockingservicestests/src/com/android/server/display/RefreshRateSettingsUtilsTest.java new file mode 100644 index 000000000000..17fba9f43707 --- /dev/null +++ b/services/tests/mockingservicestests/src/com/android/server/display/RefreshRateSettingsUtilsTest.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.display; + +import static com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE; + +import static org.junit.Assert.assertEquals; +import static org.mockito.Mockito.when; + +import android.hardware.display.DisplayManager; +import android.provider.Settings; +import android.testing.TestableContext; +import android.view.Display; + +import androidx.test.filters.SmallTest; +import androidx.test.platform.app.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; + +import com.android.internal.display.RefreshRateSettingsUtils; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@SmallTest +@RunWith(AndroidJUnit4.class) +public class RefreshRateSettingsUtilsTest { + + @Rule + public final TestableContext mContext = new TestableContext( + InstrumentationRegistry.getInstrumentation().getContext()); + + @Mock + private DisplayManager mDisplayManagerMock; + @Mock + private Display mDisplayMock; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + + mContext.addMockSystemService(DisplayManager.class, mDisplayManagerMock); + + Display.Mode[] modes = new Display.Mode[] { + new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600, + /* refreshRate= */ 60), + new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600, + /* refreshRate= */ 120), + new Display.Mode(/* modeId= */ 0, /* width= */ 800, /* height= */ 600, + /* refreshRate= */ 90) + }; + + when(mDisplayManagerMock.getDisplay(Display.DEFAULT_DISPLAY)).thenReturn(mDisplayMock); + when(mDisplayMock.getSupportedModes()).thenReturn(modes); + } + + @Test + public void testFindHighestRefreshRateForDefaultDisplay() { + when(mDisplayManagerMock.getDisplay(Display.DEFAULT_DISPLAY)).thenReturn(null); + assertEquals(DEFAULT_REFRESH_RATE, + RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(mContext), + /* delta= */ 0); + + when(mDisplayManagerMock.getDisplay(Display.DEFAULT_DISPLAY)).thenReturn(mDisplayMock); + assertEquals(120, + RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(mContext), + /* delta= */ 0); + } + + @Test + public void testGetMinRefreshRate() { + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.FORCE_PEAK_REFRESH_RATE, -1); + assertEquals(0, RefreshRateSettingsUtils.getMinRefreshRate(mContext), /* delta= */ 0); + + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.FORCE_PEAK_REFRESH_RATE, 0); + assertEquals(0, RefreshRateSettingsUtils.getMinRefreshRate(mContext), /* delta= */ 0); + + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.FORCE_PEAK_REFRESH_RATE, 1); + assertEquals(120, RefreshRateSettingsUtils.getMinRefreshRate(mContext), /* delta= */ 0); + } + + @Test + public void testGetPeakRefreshRate() { + float defaultPeakRefreshRate = 100; + + Settings.System.putInt(mContext.getContentResolver(), Settings.System.SMOOTH_DISPLAY, -1); + assertEquals(defaultPeakRefreshRate, + RefreshRateSettingsUtils.getPeakRefreshRate(mContext, defaultPeakRefreshRate), + /* delta= */ 0); + + Settings.System.putInt(mContext.getContentResolver(), Settings.System.SMOOTH_DISPLAY, 0); + assertEquals(DEFAULT_REFRESH_RATE, + RefreshRateSettingsUtils.getPeakRefreshRate(mContext, defaultPeakRefreshRate), + /* delta= */ 0); + + Settings.System.putInt(mContext.getContentResolver(), Settings.System.SMOOTH_DISPLAY, 1); + assertEquals(120, + RefreshRateSettingsUtils.getPeakRefreshRate(mContext, defaultPeakRefreshRate), + /* delta= */ 0); + } +} diff --git a/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java index 6907145542cc..42c1fd9e3321 100644 --- a/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java +++ b/services/tests/servicestests/src/com/android/server/display/mode/DisplayModeDirectorTest.java @@ -84,6 +84,7 @@ import androidx.test.filters.SmallTest; import com.android.internal.R; import com.android.internal.display.BrightnessSynchronizer; +import com.android.internal.display.RefreshRateSettingsUtils; import com.android.internal.os.BackgroundThread; import com.android.internal.util.Preconditions; import com.android.internal.util.test.FakeSettingsProvider; @@ -158,6 +159,9 @@ public class DisplayModeDirectorTest { LocalServices.addService(SensorManagerInternal.class, mSensorManagerInternalMock); LocalServices.removeServiceForTest(DisplayManagerInternal.class); LocalServices.addService(DisplayManagerInternal.class, mDisplayManagerInternalMock); + + clearSmoothDisplaySetting(); + clearForcePeakRefreshRateSetting(); } private DisplayModeDirector createDirectorFromRefreshRateArray( @@ -919,7 +923,6 @@ public class DisplayModeDirectorTest { public void testLockFpsForLowZone() throws Exception { DisplayModeDirector director = createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); - setPeakRefreshRate(90); director.getSettingsObserver().setDefaultRefreshRate(90); director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); @@ -927,6 +930,7 @@ public class DisplayModeDirectorTest { config.setRefreshRateInLowZone(90); config.setLowDisplayBrightnessThresholds(new int[] { 10 }); config.setLowAmbientBrightnessThresholds(new int[] { 20 }); + config.setDefaultPeakRefreshRate(90); Sensor lightSensor = createLightSensor(); SensorManager sensorManager = createMockSensorManager(lightSensor); @@ -977,7 +981,6 @@ public class DisplayModeDirectorTest { public void testLockFpsForHighZone() throws Exception { DisplayModeDirector director = createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); - setPeakRefreshRate(90 /*fps*/); director.getSettingsObserver().setDefaultRefreshRate(90); director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); @@ -985,6 +988,7 @@ public class DisplayModeDirectorTest { config.setRefreshRateInHighZone(60); config.setHighDisplayBrightnessThresholds(new int[] { 255 }); config.setHighAmbientBrightnessThresholds(new int[] { 8000 }); + config.setDefaultPeakRefreshRate(90); Sensor lightSensor = createLightSensor(); SensorManager sensorManager = createMockSensorManager(lightSensor); @@ -1032,16 +1036,123 @@ public class DisplayModeDirectorTest { } @Test + public void testSmoothDisplay() { + float defaultRefreshRate = 60; + int defaultPeakRefreshRate = 100; + DisplayModeDirector director = + createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); + director.getSettingsObserver().setDefaultRefreshRate(defaultRefreshRate); + director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); + + final FakeDeviceConfig config = mInjector.getDeviceConfig(); + config.setDefaultPeakRefreshRate(defaultPeakRefreshRate); + + Sensor lightSensor = createLightSensor(); + SensorManager sensorManager = createMockSensorManager(lightSensor); + director.start(sensorManager); + + // Default value of the setting + + Vote vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */ + defaultPeakRefreshRate); + vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */ + Float.POSITIVE_INFINITY); + vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_DEFAULT_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */ + defaultRefreshRate); + + setSmoothDisplayEnabled(false); + + vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */ + RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE); + vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */ + Float.POSITIVE_INFINITY); + vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_DEFAULT_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */ + defaultRefreshRate); + + setSmoothDisplayEnabled(true); + + vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */ + RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(mContext)); + vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */ + Float.POSITIVE_INFINITY); + vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_DEFAULT_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */ + defaultRefreshRate); + } + + @Test + public void testForcePeakRefreshRate() { + float defaultRefreshRate = 60; + DisplayModeDirector director = + createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); + director.getSettingsObserver().setDefaultRefreshRate(defaultRefreshRate); + director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); + + Sensor lightSensor = createLightSensor(); + SensorManager sensorManager = createMockSensorManager(lightSensor); + director.start(sensorManager); + + setForcePeakRefreshRateEnabled(false); + setSmoothDisplayEnabled(false); + + Vote vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */ + RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE); + vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, + /* frameRateHigh= */ Float.POSITIVE_INFINITY); + vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_DEFAULT_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */ + defaultRefreshRate); + + setForcePeakRefreshRateEnabled(true); + + vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */ + RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(mContext)); + vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ + RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay(mContext), + /* frameRateHigh= */ Float.POSITIVE_INFINITY); + vote = director.getVote(Display.DEFAULT_DISPLAY, + Vote.PRIORITY_DEFAULT_RENDER_FRAME_RATE); + assertVoteForRenderFrameRateRange(vote, /* frameRateLow= */ 0, /* frameRateHigh= */ + defaultRefreshRate); + } + + @Test public void testSensorRegistration() { // First, configure brightness zones or DMD won't register for sensor data. final FakeDeviceConfig config = mInjector.getDeviceConfig(); config.setRefreshRateInHighZone(60); config.setHighDisplayBrightnessThresholds(new int[] { 255 }); config.setHighAmbientBrightnessThresholds(new int[] { 8000 }); + config.setDefaultPeakRefreshRate(90); DisplayModeDirector director = createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); - setPeakRefreshRate(90 /*fps*/); director.getSettingsObserver().setDefaultRefreshRate(90); director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); @@ -2417,10 +2528,10 @@ public class DisplayModeDirectorTest { config.setRefreshRateInHighZone(60); config.setHighDisplayBrightnessThresholds(new int[] { 255 }); config.setHighAmbientBrightnessThresholds(new int[] { 8000 }); + config.setDefaultPeakRefreshRate(90); DisplayModeDirector director = createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0); - setPeakRefreshRate(90 /*fps*/); director.getSettingsObserver().setDefaultRefreshRate(90); director.getBrightnessObserver().setDefaultDisplayState(Display.STATE_ON); @@ -2671,10 +2782,30 @@ public class DisplayModeDirectorTest { listener.onDisplayChanged(DISPLAY_ID); } - private void setPeakRefreshRate(float fps) { - Settings.System.putFloat(mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE, - fps); - mInjector.notifyPeakRefreshRateChanged(); + private void setSmoothDisplayEnabled(boolean enabled) { + Settings.System.putInt(mContext.getContentResolver(), Settings.System.SMOOTH_DISPLAY, + enabled ? 1 : 0); + mInjector.notifySmoothDisplaySettingChanged(); + waitForIdleSync(); + } + + private void clearSmoothDisplaySetting() { + Settings.System.putInt(mContext.getContentResolver(), Settings.System.SMOOTH_DISPLAY, -1); + mInjector.notifySmoothDisplaySettingChanged(); + waitForIdleSync(); + } + + private void setForcePeakRefreshRateEnabled(boolean enabled) { + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.FORCE_PEAK_REFRESH_RATE, enabled ? 1 : 0); + mInjector.notifyForcePeakRefreshRateSettingChanged(); + waitForIdleSync(); + } + + private void clearForcePeakRefreshRateSetting() { + Settings.System.putInt(mContext.getContentResolver(), + Settings.System.FORCE_PEAK_REFRESH_RATE, -1); + mInjector.notifySmoothDisplaySettingChanged(); waitForIdleSync(); } @@ -2720,7 +2851,8 @@ public class DisplayModeDirectorTest { public static class FakesInjector implements DisplayModeDirector.Injector { private final FakeDeviceConfig mDeviceConfig; private ContentObserver mBrightnessObserver; - private ContentObserver mPeakRefreshRateObserver; + private ContentObserver mSmoothDisplaySettingObserver; + private ContentObserver mForcePeakRefreshRateSettingObserver; FakesInjector() { mDeviceConfig = new FakeDeviceConfig(); @@ -2732,9 +2864,15 @@ public class DisplayModeDirectorTest { } @Override - public void registerPeakRefreshRateObserver(@NonNull ContentResolver cr, + public void registerSmoothDisplayObserver(@NonNull ContentResolver cr, + @NonNull ContentObserver observer) { + mSmoothDisplaySettingObserver = observer; + } + + @Override + public void registerForcePeakRefreshRateObserver(@NonNull ContentResolver cr, @NonNull ContentObserver observer) { - mPeakRefreshRateObserver = observer; + mForcePeakRefreshRateSettingObserver = observer; } @Override @@ -2775,10 +2913,17 @@ public class DisplayModeDirectorTest { ApplicationProvider.getApplicationContext().getResources()); } - void notifyPeakRefreshRateChanged() { - if (mPeakRefreshRateObserver != null) { - mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/, - PEAK_REFRESH_RATE_URI); + void notifySmoothDisplaySettingChanged() { + if (mSmoothDisplaySettingObserver != null) { + mSmoothDisplaySettingObserver.dispatchChange(false /*selfChange*/, + SMOOTH_DISPLAY_URI); + } + } + + void notifyForcePeakRefreshRateSettingChanged() { + if (mForcePeakRefreshRateSettingObserver != null) { + mForcePeakRefreshRateSettingObserver.dispatchChange(false /*selfChange*/, + FORCE_PEAK_REFRESH_RATE_URI); } } } |