Settings: Add peak refresh rate list preference
* AOSP "Smooth display" setting is just a toggle,
some devices support multiple refresh rates so
add support for it with a ListPreference.
Change-Id: I3da3d2b86e61ed3caf9af5770d8bdb4485817b97
diff --git a/res/values/cm_strings.xml b/res/values/cm_strings.xml
index 19825c2..1318a66 100644
--- a/res/values/cm_strings.xml
+++ b/res/values/cm_strings.xml
@@ -47,6 +47,9 @@
<!-- Whether the dots will be drawn when using the lockscreen pattern -->
<string name="lockpattern_settings_enable_dots_title">Show pattern dots</string>
+ <!-- Max refresh rate -->
+ <string name="max_refresh_rate_title">Peak refresh rate</string>
+
<!-- PIN scramble -->
<string name="unlock_scramble_pin_layout_title">Scramble layout</string>
<string name="unlock_scramble_pin_layout_summary">Scramble PIN layout when unlocking device</string>
diff --git a/res/values/leaf_config.xml b/res/values/leaf_config.xml
new file mode 100644
index 0000000..1f9d592
--- /dev/null
+++ b/res/values/leaf_config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 The LeafOS 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.
+-->
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+ <!-- Whether to show peak refresh rate in display settings -->
+ <bool name="config_show_peak_refresh_rate_switch">false</bool>
+</resources>
diff --git a/res/xml/display_settings.xml b/res/xml/display_settings.xml
index 4b84e4c..cd8898f 100644
--- a/res/xml/display_settings.xml
+++ b/res/xml/display_settings.xml
@@ -158,6 +158,12 @@
android:summary="@string/display_white_balance_summary"
settings:controller="com.android.settings.display.DisplayWhiteBalancePreferenceController"/>
+ <ListPreference
+ android:key="max_refresh_rate"
+ android:title="@string/max_refresh_rate_title"
+ android:summary="@string/summary_placeholder"
+ settings:controller="com.android.settings.display.PeakRefreshRateListPreferenceController" />
+
<SwitchPreferenceCompat
android:key="peak_refresh_rate"
android:title="@string/peak_refresh_rate_title"
diff --git a/src/com/android/settings/display/PeakRefreshRateListPreferenceController.java b/src/com/android/settings/display/PeakRefreshRateListPreferenceController.java
new file mode 100644
index 0000000..e4f4a07
--- /dev/null
+++ b/src/com/android/settings/display/PeakRefreshRateListPreferenceController.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ * Copyright (C) 2021 The LineageOS 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.display;
+
+import android.content.Context;
+import android.hardware.display.DisplayManager;
+import android.os.Handler;
+import android.provider.DeviceConfig;
+import android.provider.Settings;
+import android.util.Log;
+import android.view.Display;
+
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnStart;
+import com.android.settingslib.core.lifecycle.events.OnStop;
+
+import java.util.ArrayList;
+import java.util.concurrent.Executor;
+import java.util.List;
+import java.util.Locale;
+
+public class PeakRefreshRateListPreferenceController extends BasePreferenceController
+ implements LifecycleObserver, OnStart, OnStop, Preference.OnPreferenceChangeListener {
+
+ private static float DEFAULT_REFRESH_RATE = 60f;
+
+ private static final String TAG = "PeakRefreshRatePrefCtr";
+ private static final float INVALIDATE_REFRESH_RATE = -1f;
+
+ private final Handler mHandler;
+ private final IDeviceConfigChange mOnDeviceConfigChange;
+ private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
+ private ListPreference mListPreference;
+
+ private List<String> mEntries = new ArrayList<>();
+ private List<String> mValues = new ArrayList<>();
+
+ private interface IDeviceConfigChange {
+ void onDefaultRefreshRateChanged();
+ }
+
+ public PeakRefreshRateListPreferenceController(Context context, String key) {
+ super(context, key);
+ mHandler = new Handler(context.getMainLooper());
+ mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
+ mOnDeviceConfigChange =
+ new IDeviceConfigChange() {
+ public void onDefaultRefreshRateChanged() {
+ updateState(mListPreference);
+ }
+ };
+
+ final DisplayManager dm = mContext.getSystemService(DisplayManager.class);
+ final Display display = dm.getDisplay(Display.DEFAULT_DISPLAY);
+
+ if (display == null) {
+ Log.w(TAG, "No valid default display device");
+ } else {
+ Display.Mode mode = display.getMode();
+ Display.Mode[] modes = display.getSupportedModes();
+ for (Display.Mode m : modes) {
+ if (m.getPhysicalWidth() == mode.getPhysicalWidth() &&
+ m.getPhysicalHeight() == mode.getPhysicalHeight()) {
+ mEntries.add(String.format("%.02fHz", m.getRefreshRate())
+ .replaceAll("[\\.,]00", ""));
+ mValues.add(String.format(Locale.US, "%.02f", m.getRefreshRate()));
+ }
+ }
+ }
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+
+ mListPreference = screen.findPreference(getPreferenceKey());
+ mListPreference.setEntries(mEntries.toArray(new String[mEntries.size()]));
+ mListPreference.setEntryValues(mValues.toArray(new String[mValues.size()]));
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (mContext.getResources().getBoolean(R.bool.config_show_peak_refresh_rate_switch)) {
+ return AVAILABLE;
+ } else {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ final float currentValue = Settings.System.getFloat(mContext.getContentResolver(),
+ Settings.System.PEAK_REFRESH_RATE, getDefaultPeakRefreshRate());
+ int index = mListPreference.findIndexOfValue(
+ String.format(Locale.US, "%.02f", currentValue));
+ if (index < 0) index = 0;
+ mListPreference.setValueIndex(index);
+ mListPreference.setSummary(mListPreference.getEntries()[index]);
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ Settings.System.putFloat(mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE,
+ Float.valueOf((String) newValue));
+ updateState(preference);
+ return true;
+ }
+
+ @Override
+ public void onStart() {
+ mDeviceConfigDisplaySettings.startListening();
+ }
+
+ @Override
+ public void onStop() {
+ mDeviceConfigDisplaySettings.stopListening();
+ }
+
+ 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;
+ }
+
+ private class DeviceConfigDisplaySettings
+ implements DeviceConfig.OnPropertiesChangedListener, Executor {
+ public void startListening() {
+ DeviceConfig.addOnPropertiesChangedListener(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ this /* Executor */,
+ this /* Listener */);
+ }
+
+ public void stopListening() {
+ DeviceConfig.removeOnPropertiesChangedListener(this);
+ }
+
+ public float getDefaultPeakRefreshRate() {
+ float defaultPeakRefreshRate =
+ DeviceConfig.getFloat(
+ DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+ DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT,
+ INVALIDATE_REFRESH_RATE);
+ Log.d(TAG, "DeviceConfig getDefaultPeakRefreshRate : " + defaultPeakRefreshRate);
+
+ return defaultPeakRefreshRate;
+ }
+
+ @Override
+ public void onPropertiesChanged(DeviceConfig.Properties properties) {
+ // Got notified if any property has been changed in NAMESPACE_DISPLAY_MANAGER. The
+ // KEY_PEAK_REFRESH_RATE_DEFAULT value could be added, changed, removed or unchanged.
+ // Just force a UI update for any case.
+ if (mOnDeviceConfigChange != null) {
+ mOnDeviceConfigChange.onDefaultRefreshRateChanged();
+ updateState(mListPreference);
+ }
+ }
+
+ @Override
+ public void execute(Runnable runnable) {
+ if (mHandler != null) {
+ mHandler.post(runnable);
+ }
+ }
+ }
+
+ private float getDefaultPeakRefreshRate() {
+ float defaultPeakRefreshRate = mDeviceConfigDisplaySettings.getDefaultPeakRefreshRate();
+ if (defaultPeakRefreshRate == INVALIDATE_REFRESH_RATE) {
+ defaultPeakRefreshRate = (float) mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_defaultPeakRefreshRate);
+ }
+
+ return defaultPeakRefreshRate;
+ }
+}