From f035eefe67413aa835f57e5c3064ec777c25959b Mon Sep 17 00:00:00 2001 From: Jacky Wang Date: Thu, 31 Oct 2024 09:47:04 +0800 Subject: [PATCH] [Catalyst] Implement datastore for Smooth display NO_IFTTT=Catalyst only Bug: 374936314 Flag: com.android.settings.flags.catalyst_display_settings_screen Test: manual & adb shell settings get/put/delete system peak_refresh_rate Change-Id: Idc9379935934c32ef040be6c4c838e5fbb65319d --- .../PeakRefreshRateSwitchPreference.kt | 110 ++++++++++++------ 1 file changed, 72 insertions(+), 38 deletions(-) diff --git a/src/com/android/settings/display/PeakRefreshRateSwitchPreference.kt b/src/com/android/settings/display/PeakRefreshRateSwitchPreference.kt index 793b0e226a7..5302fce5451 100644 --- a/src/com/android/settings/display/PeakRefreshRateSwitchPreference.kt +++ b/src/com/android/settings/display/PeakRefreshRateSwitchPreference.kt @@ -18,53 +18,51 @@ package com.android.settings.display import android.content.Context import android.hardware.display.DisplayManager import android.provider.DeviceConfig -import android.util.Log +import android.provider.Settings.System.PEAK_REFRESH_RATE import com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE import com.android.internal.display.RefreshRateSettingsUtils.findHighestRefreshRateAmongAllDisplays import com.android.internal.display.RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay import com.android.server.display.feature.flags.Flags import com.android.settings.R import com.android.settingslib.datastore.HandlerExecutor +import com.android.settingslib.datastore.KeyValueStore +import com.android.settingslib.datastore.KeyedObservableDelegate +import com.android.settingslib.datastore.SettingsStore import com.android.settingslib.datastore.SettingsSystemStore import com.android.settingslib.metadata.PreferenceAvailabilityProvider import com.android.settingslib.metadata.PreferenceLifecycleContext import com.android.settingslib.metadata.PreferenceLifecycleProvider import com.android.settingslib.metadata.PreferenceSummaryProvider import com.android.settingslib.metadata.SwitchPreference -import com.android.settingslib.preference.SwitchPreferenceBinding import kotlin.math.roundToInt // LINT.IfChange class PeakRefreshRateSwitchPreference : - SwitchPreference("peak_refresh_rate", R.string.peak_refresh_rate_title), - SwitchPreferenceBinding, + SwitchPreference(PEAK_REFRESH_RATE, R.string.peak_refresh_rate_title), PreferenceAvailabilityProvider, PreferenceSummaryProvider, PreferenceLifecycleProvider { private var propertiesChangedListener: DeviceConfig.OnPropertiesChangedListener? = null - override fun storage(context: Context) = SettingsSystemStore.get(context) + override fun storage(context: Context): KeyValueStore = + PeakRefreshRateStore(context, SettingsSystemStore.get(context)) override fun isAvailable(context: Context) = context.resources.getBoolean(R.bool.config_show_smooth_display) && - (getPeakRefreshRate(context) > DEFAULT_REFRESH_RATE) + context.peakRefreshRate > DEFAULT_REFRESH_RATE - override fun getSummary(context: Context) = - context.getString( - R.string.peak_refresh_rate_summary, - getPeakRefreshRate(context).roundToInt(), - ) + override fun getSummary(context: Context): CharSequence? = + context.getString(R.string.peak_refresh_rate_summary, context.peakRefreshRate.roundToInt()) override fun onStart(context: PreferenceLifecycleContext) { val listener = - object : DeviceConfig.OnPropertiesChangedListener { + DeviceConfig.OnPropertiesChangedListener { // 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. - override fun onPropertiesChanged(properties: DeviceConfig.Properties) = - context.notifyPreferenceChange(this@PeakRefreshRateSwitchPreference) + context.notifyPreferenceChange(this) } propertiesChangedListener = listener @@ -83,38 +81,74 @@ class PeakRefreshRateSwitchPreference : } } - private fun getPeakRefreshRate(context: Context): Float = - Math.round( - when { - Flags.backUpSmoothDisplayAndForcePeakRefreshRate() -> - findHighestRefreshRateAmongAllDisplays(context) - else -> findHighestRefreshRateForDefaultDisplay(context) - } - ) - .toFloat() + @Suppress("UNCHECKED_CAST") + private class PeakRefreshRateStore( + private val context: Context, + private val settingsStore: SettingsStore, + ) : KeyedObservableDelegate(settingsStore), KeyValueStore { - private fun getDefaultPeakRefreshRate(context: Context): Float { - var defaultPeakRefreshRate = - DeviceConfig.getFloat( - DeviceConfig.NAMESPACE_DISPLAY_MANAGER, - DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT, - INVALIDATE_REFRESH_RATE, - ) + override fun contains(key: String) = settingsStore.contains(key) - if (defaultPeakRefreshRate == INVALIDATE_REFRESH_RATE) { - defaultPeakRefreshRate = - context.resources - .getInteger(com.android.internal.R.integer.config_defaultPeakRefreshRate) - .toFloat() + override fun getDefaultValue(key: String, valueType: Class): T? { + if (key != PEAK_REFRESH_RATE) return super.getDefaultValue(key, valueType) + return context.defaultPeakRefreshRate.refreshRateAsBoolean(context) as T } - Log.d(TAG, "DeviceConfig getDefaultPeakRefreshRate : $defaultPeakRefreshRate") - return defaultPeakRefreshRate + override fun getValue(key: String, valueType: Class): T? { + if (key != PEAK_REFRESH_RATE) return null + val refreshRate = + settingsStore.getFloat(PEAK_REFRESH_RATE) ?: context.defaultPeakRefreshRate + return refreshRate.refreshRateAsBoolean(context) as T + } + + private fun Float.refreshRateAsBoolean(context: Context) = + this.isInfinite() || roundToInt() == context.peakRefreshRate.roundToInt() + + override fun setValue(key: String, valueType: Class, value: T?) = + when { + key != PEAK_REFRESH_RATE -> {} + value == null -> settingsStore.setFloat(PEAK_REFRESH_RATE, null) + else -> { + val peakRefreshRate = + if (value as Boolean) context.refreshRateIfON() else DEFAULT_REFRESH_RATE + settingsStore.setFloat(PEAK_REFRESH_RATE, peakRefreshRate) + } + } + + private fun Context.refreshRateIfON() = + when { + Flags.backUpSmoothDisplayAndForcePeakRefreshRate() -> Float.POSITIVE_INFINITY + else -> peakRefreshRate + } } companion object { - private const val TAG: String = "PeakRefreshRateSwitchPreference" private const val INVALIDATE_REFRESH_RATE: Float = -1f + + private val Context.peakRefreshRate: Float + get() = + Math.round( + when { + Flags.backUpSmoothDisplayAndForcePeakRefreshRate() -> + findHighestRefreshRateAmongAllDisplays(this) + else -> findHighestRefreshRateForDefaultDisplay(this) + } + ) + .toFloat() + + private val Context.defaultPeakRefreshRate: Float + get() { + val defaultPeakRefreshRate = + DeviceConfig.getFloat( + DeviceConfig.NAMESPACE_DISPLAY_MANAGER, + DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_DEFAULT, + INVALIDATE_REFRESH_RATE, + ) + if (defaultPeakRefreshRate != INVALIDATE_REFRESH_RATE) return defaultPeakRefreshRate + return resources + .getInteger(com.android.internal.R.integer.config_defaultPeakRefreshRate) + .toFloat() + } } } // LINT.ThenChange(PeakRefreshRatePreferenceController.java)