diff --git a/res/values/strings.xml b/res/values/strings.xml index e0c5d5d33e1..847335750f8 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -2752,6 +2752,10 @@ Smooth Display Automatically raises the refresh rate from 60 to 90 Hz for some content. Increases battery usage. + + Smooth Display + + Highest refresh rate for improved touch responsiveness & animation quality. Increases battery usage. Screen attention diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml index e8605894f6d..746a51c4b9d 100644 --- a/res/xml/development_settings.xml +++ b/res/xml/development_settings.xml @@ -256,6 +256,11 @@ android:title="@string/overlay_settings_title" android:summary="@string/overlay_settings_summary" /> + + DEFAULT_REFRESH_RATE; + } else { + return false; + } + } + + @Override + protected void onDeveloperOptionsSwitchDisabled() { + super.onDeveloperOptionsSwitchDisabled(); + Settings.System.putFloat(mContext.getContentResolver(), + Settings.System.MIN_REFRESH_RATE, NO_CONFIG); + + ((SwitchPreference) mPreference).setChecked(false); + } + + @VisibleForTesting + void forcePeakRefreshRate(boolean enable) { + final float peakRefreshRate = enable ? mPeakRefreshRate : NO_CONFIG; + Settings.System.putFloat(mContext.getContentResolver(), + Settings.System.MIN_REFRESH_RATE, peakRefreshRate); + } + + boolean isForcePeakRefreshRateEnabled() { + final float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(), + Settings.System.MIN_REFRESH_RATE, NO_CONFIG); + + return peakRefreshRate >= mPeakRefreshRate; + } + + private float findPeakRefreshRate(Display.Mode[] modes) { + float peakRefreshRate = DEFAULT_REFRESH_RATE; + for (Display.Mode mode : modes) { + if (Math.round(mode.getRefreshRate()) > DEFAULT_REFRESH_RATE) { + peakRefreshRate = mode.getRefreshRate(); + } + } + + return peakRefreshRate; + } +} diff --git a/tests/robotests/src/com/android/settings/development/ForcePeakRefreshRatePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/ForcePeakRefreshRatePreferenceControllerTest.java new file mode 100644 index 00000000000..2e93d5ef9ca --- /dev/null +++ b/tests/robotests/src/com/android/settings/development/ForcePeakRefreshRatePreferenceControllerTest.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2020 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.settings.development; + +import static com.android.settings.development.ForcePeakRefreshRatePreferenceController.DEFAULT_REFRESH_RATE; +import static com.android.settings.development.ForcePeakRefreshRatePreferenceController.NO_CONFIG; +import static com.google.common.truth.Truth.assertThat; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.provider.Settings; + +import androidx.preference.PreferenceScreen; +import androidx.preference.SwitchPreference; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import android.util.Log; + +@RunWith(RobolectricTestRunner.class) +public class ForcePeakRefreshRatePreferenceControllerTest { + + @Mock + private SwitchPreference mPreference; + @Mock + private PreferenceScreen mScreen; + + private Context mContext; + private ForcePeakRefreshRatePreferenceController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = RuntimeEnvironment.application; + mController = new ForcePeakRefreshRatePreferenceController(mContext); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); + when(mPreference.getKey()).thenReturn(mController.getPreferenceKey()); + mController.displayPreference(mScreen); + } + + @Test + public void onPreferenceChange_preferenceChecked_shouldEnableForcePeak() { + mController.mPeakRefreshRate = 88f; + + mController.onPreferenceChange(mPreference, true); + + assertThat(Settings.System.getFloat(mContext.getContentResolver(), + Settings.System.MIN_REFRESH_RATE, NO_CONFIG)).isEqualTo(88f); + } + + @Test + public void onPreferenceChange_preferenceUnchecked_shouldDisableForcePeak() { + mController.mPeakRefreshRate = 88f; + + mController.onPreferenceChange(mPreference, false); + + assertThat(Settings.System.getFloat(mContext.getContentResolver(), + Settings.System.MIN_REFRESH_RATE, NO_CONFIG)).isEqualTo(NO_CONFIG); + } + + @Test + public void updateState_enableForcePeak_shouldCheckedToggle() { + mController.mPeakRefreshRate = 88f; + mController.forcePeakRefreshRate(true); + + mController.updateState(mPreference); + + verify(mPreference).setChecked(true); + } + + @Test + public void updateState_disableForcePeak_shouldUncheckedToggle() { + mController.mPeakRefreshRate = 88f; + mController.forcePeakRefreshRate(false); + + mController.updateState(mPreference); + + verify(mPreference).setChecked(false); + } + + @Test + @Config(qualifiers = "mcc999") + public void isAvailable_withConfigNoShow_returnUnsupported() { + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void isAvailable_refreshRateLargerThanDefault_returnTrue() { + mController.mPeakRefreshRate = DEFAULT_REFRESH_RATE + 1; + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void getAvailabilityStatus_refreshRateEqualToDefault_returnFalse() { + mController.mPeakRefreshRate = DEFAULT_REFRESH_RATE; + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void onDeveloperOptionsDisabled_shouldDisablePreference() { + mController.onDeveloperOptionsSwitchDisabled(); + + assertThat(Settings.System.getFloat(mContext.getContentResolver(), + Settings.System.MIN_REFRESH_RATE, -1f)).isEqualTo(NO_CONFIG); + assertThat(mPreference.isChecked()).isFalse(); + assertThat(mPreference.isEnabled()).isFalse(); + } +}