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