1 /* 2 * Copyright (C) 2020 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.settings.development; 18 19 import android.content.Context; 20 import android.hardware.display.DisplayManager; 21 import android.provider.Settings; 22 import android.util.Log; 23 import android.view.Display; 24 25 import androidx.annotation.VisibleForTesting; 26 import androidx.preference.Preference; 27 import androidx.preference.PreferenceScreen; 28 import androidx.preference.SwitchPreference; 29 30 import com.android.settings.R; 31 import com.android.settings.core.PreferenceControllerMixin; 32 import com.android.settingslib.development.DeveloperOptionsPreferenceController; 33 34 public class ForcePeakRefreshRatePreferenceController extends DeveloperOptionsPreferenceController 35 implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin { 36 37 @VisibleForTesting 38 static float DEFAULT_REFRESH_RATE = 60f; 39 40 @VisibleForTesting 41 static float NO_CONFIG = 0f; 42 43 @VisibleForTesting 44 float mPeakRefreshRate; 45 46 private static final String TAG = "ForcePeakRefreshRateCtr"; 47 private static final String PREFERENCE_KEY = "pref_key_peak_refresh_rate"; 48 ForcePeakRefreshRatePreferenceController(Context context)49 public ForcePeakRefreshRatePreferenceController(Context context) { 50 super(context); 51 52 final DisplayManager dm = context.getSystemService(DisplayManager.class); 53 final Display display = dm.getDisplay(Display.DEFAULT_DISPLAY); 54 55 if (display == null) { 56 Log.w(TAG, "No valid default display device"); 57 mPeakRefreshRate = DEFAULT_REFRESH_RATE; 58 } else { 59 mPeakRefreshRate = findPeakRefreshRate(display.getSupportedModes()); 60 } 61 62 Log.d(TAG, "DEFAULT_REFRESH_RATE : " + DEFAULT_REFRESH_RATE 63 + " mPeakRefreshRate : " + mPeakRefreshRate); 64 } 65 66 @Override getPreferenceKey()67 public String getPreferenceKey() { 68 return PREFERENCE_KEY; 69 } 70 71 @Override displayPreference(PreferenceScreen screen)72 public void displayPreference(PreferenceScreen screen) { 73 super.displayPreference(screen); 74 mPreference = screen.findPreference(getPreferenceKey()); 75 } 76 77 @Override onPreferenceChange(Preference preference, Object newValue)78 public boolean onPreferenceChange(Preference preference, Object newValue) { 79 final boolean isEnabled = (Boolean) newValue; 80 forcePeakRefreshRate(isEnabled); 81 82 return true; 83 } 84 85 @Override updateState(Preference preference)86 public void updateState(Preference preference) { 87 ((SwitchPreference) mPreference).setChecked(isForcePeakRefreshRateEnabled()); 88 } 89 90 @Override isAvailable()91 public boolean isAvailable() { 92 if (mContext.getResources().getBoolean(R.bool.config_show_smooth_display)) { 93 return mPeakRefreshRate > DEFAULT_REFRESH_RATE; 94 } else { 95 return false; 96 } 97 } 98 99 @Override onDeveloperOptionsSwitchDisabled()100 protected void onDeveloperOptionsSwitchDisabled() { 101 super.onDeveloperOptionsSwitchDisabled(); 102 Settings.System.putFloat(mContext.getContentResolver(), 103 Settings.System.MIN_REFRESH_RATE, NO_CONFIG); 104 105 ((SwitchPreference) mPreference).setChecked(false); 106 } 107 108 @VisibleForTesting forcePeakRefreshRate(boolean enable)109 void forcePeakRefreshRate(boolean enable) { 110 final float peakRefreshRate = enable ? mPeakRefreshRate : NO_CONFIG; 111 Settings.System.putFloat(mContext.getContentResolver(), 112 Settings.System.MIN_REFRESH_RATE, peakRefreshRate); 113 } 114 isForcePeakRefreshRateEnabled()115 boolean isForcePeakRefreshRateEnabled() { 116 final float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(), 117 Settings.System.MIN_REFRESH_RATE, NO_CONFIG); 118 119 return peakRefreshRate >= mPeakRefreshRate; 120 } 121 findPeakRefreshRate(Display.Mode[] modes)122 private float findPeakRefreshRate(Display.Mode[] modes) { 123 float peakRefreshRate = DEFAULT_REFRESH_RATE; 124 for (Display.Mode mode : modes) { 125 if (Math.round(mode.getRefreshRate()) > peakRefreshRate) { 126 peakRefreshRate = mode.getRefreshRate(); 127 } 128 } 129 130 return peakRefreshRate; 131 } 132 } 133