• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.display;
18 
19 import static com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE;
20 import static com.android.internal.display.RefreshRateSettingsUtils.findHighestRefreshRateAmongAllDisplays;
21 import static com.android.internal.display.RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay;
22 
23 import android.content.Context;
24 import android.hardware.display.DisplayManager;
25 import android.os.Handler;
26 import android.provider.DeviceConfig;
27 import android.provider.Settings;
28 import android.util.Log;
29 
30 import androidx.annotation.VisibleForTesting;
31 import androidx.preference.Preference;
32 import androidx.preference.PreferenceScreen;
33 
34 import com.android.server.display.feature.flags.Flags;
35 import com.android.settings.R;
36 import com.android.settings.core.TogglePreferenceController;
37 import com.android.settingslib.core.lifecycle.LifecycleObserver;
38 import com.android.settingslib.core.lifecycle.events.OnStart;
39 import com.android.settingslib.core.lifecycle.events.OnStop;
40 
41 import java.util.concurrent.Executor;
42 
43 // LINT.IfChange
44 public class PeakRefreshRatePreferenceController extends TogglePreferenceController
45         implements LifecycleObserver, OnStart, OnStop {
46 
47     @VisibleForTesting float mPeakRefreshRate;
48 
49     private static final String TAG = "RefreshRatePrefCtr";
50     private static final float INVALIDATE_REFRESH_RATE = -1f;
51 
52     private final Handler mHandler;
53     private final IDeviceConfigChange mOnDeviceConfigChange;
54     private DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
55     private Preference mPreference;
56 
57     private interface IDeviceConfigChange {
onDefaultRefreshRateChanged()58         void onDefaultRefreshRateChanged();
59     }
60 
PeakRefreshRatePreferenceController(Context context, String key)61     public PeakRefreshRatePreferenceController(Context context, String key) {
62         super(context, key);
63         mHandler = new Handler(context.getMainLooper());
64         mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
65         mOnDeviceConfigChange =
66                 new IDeviceConfigChange() {
67                     public void onDefaultRefreshRateChanged() {
68                         updateState(mPreference);
69                     }
70                 };
71         mPeakRefreshRate = Math.round(Flags.backUpSmoothDisplayAndForcePeakRefreshRate()
72                 ? findHighestRefreshRateAmongAllDisplays(context)
73                 : findHighestRefreshRateForDefaultDisplay(context));
74         Log.d(
75                 TAG,
76                 "DEFAULT_REFRESH_RATE : "
77                         + DEFAULT_REFRESH_RATE
78                         + " mPeakRefreshRate : "
79                         + mPeakRefreshRate);
80     }
81 
82     @Override
displayPreference(PreferenceScreen screen)83     public void displayPreference(PreferenceScreen screen) {
84         super.displayPreference(screen);
85 
86         int defaultPeakRefreshRate = Math.round(mPeakRefreshRate);
87 
88         mPreference = screen.findPreference(getPreferenceKey());
89         mPreference.setSummary(mContext.getString(
90                 R.string.peak_refresh_rate_summary, defaultPeakRefreshRate));
91     }
92 
93     @Override
getAvailabilityStatus()94     public int getAvailabilityStatus() {
95         if (mContext.getResources().getBoolean(R.bool.config_show_smooth_display)) {
96             return mPeakRefreshRate > DEFAULT_REFRESH_RATE ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
97         } else {
98             return UNSUPPORTED_ON_DEVICE;
99         }
100     }
101 
102     @Override
isChecked()103     public boolean isChecked() {
104         final float peakRefreshRate =
105                 Settings.System.getFloat(
106                         mContext.getContentResolver(),
107                         Settings.System.PEAK_REFRESH_RATE,
108                         getDefaultPeakRefreshRate());
109         return Math.round(peakRefreshRate) == Math.round(mPeakRefreshRate)
110                 || Float.isInfinite(peakRefreshRate);
111     }
112 
113     @Override
setChecked(boolean isChecked)114     public boolean setChecked(boolean isChecked) {
115         final float valueIfChecked = Flags.backUpSmoothDisplayAndForcePeakRefreshRate()
116                 ? Float.POSITIVE_INFINITY : mPeakRefreshRate;
117         final float peakRefreshRate = isChecked ? valueIfChecked : DEFAULT_REFRESH_RATE;
118         Log.d(TAG, "setChecked to : " + peakRefreshRate);
119 
120         return Settings.System.putFloat(
121                 mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE, peakRefreshRate);
122     }
123 
124     @Override
getSliceHighlightMenuRes()125     public int getSliceHighlightMenuRes() {
126         return R.string.menu_key_display;
127     }
128 
129     @Override
onStart()130     public void onStart() {
131         mDeviceConfigDisplaySettings.startListening();
132     }
133 
134     @Override
onStop()135     public void onStop() {
136         mDeviceConfigDisplaySettings.stopListening();
137     }
138 
139     @VisibleForTesting
injectDeviceConfigDisplaySettings( DeviceConfigDisplaySettings deviceConfigDisplaySettings)140     void injectDeviceConfigDisplaySettings(
141             DeviceConfigDisplaySettings deviceConfigDisplaySettings) {
142         mDeviceConfigDisplaySettings = deviceConfigDisplaySettings;
143     }
144 
145     @VisibleForTesting
146     class DeviceConfigDisplaySettings
147             implements DeviceConfig.OnPropertiesChangedListener, Executor {
startListening()148         public void startListening() {
149             DeviceConfig.addOnPropertiesChangedListener(
150                     DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
151                     this /* Executor */,
152                     this /* Listener */);
153         }
154 
stopListening()155         public void stopListening() {
156             DeviceConfig.removeOnPropertiesChangedListener(this);
157         }
158 
getDefaultPeakRefreshRate()159         public float getDefaultPeakRefreshRate() {
160             float defaultPeakRefreshRate =
161                     DeviceConfig.getFloat(
162                             DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
163                             DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT,
164                             INVALIDATE_REFRESH_RATE);
165             Log.d(TAG, "DeviceConfig getDefaultPeakRefreshRate : " + defaultPeakRefreshRate);
166 
167             return defaultPeakRefreshRate;
168         }
169 
170         @Override
onPropertiesChanged(DeviceConfig.Properties properties)171         public void onPropertiesChanged(DeviceConfig.Properties properties) {
172             // Got notified if any property has been changed in NAMESPACE_DISPLAY_MANAGER. The
173             // KEY_PEAK_REFRESH_RATE_DEFAULT value could be added, changed, removed or unchanged.
174             // Just force a UI update for any case.
175             if (mOnDeviceConfigChange != null) {
176                 mOnDeviceConfigChange.onDefaultRefreshRateChanged();
177                 updateState(mPreference);
178             }
179         }
180 
181         @Override
execute(Runnable runnable)182         public void execute(Runnable runnable) {
183             if (mHandler != null) {
184                 mHandler.post(runnable);
185             }
186         }
187     }
188 
getDefaultPeakRefreshRate()189     private float getDefaultPeakRefreshRate() {
190         float defaultPeakRefreshRate = mDeviceConfigDisplaySettings.getDefaultPeakRefreshRate();
191         if (defaultPeakRefreshRate == INVALIDATE_REFRESH_RATE) {
192             defaultPeakRefreshRate = (float) mContext.getResources().getInteger(
193                     com.android.internal.R.integer.config_defaultPeakRefreshRate);
194         }
195 
196         Log.d(TAG, "DeviceConfig getDefaultPeakRefreshRate : " + defaultPeakRefreshRate);
197         return defaultPeakRefreshRate;
198     }
199 }
200 // LINT.ThenChange(PeakRefreshRateSwitchPreference.kt)
201