| /* |
| * Copyright (C) 2020 The Android Open Source 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 static com.android.internal.display.RefreshRateSettingsUtils.DEFAULT_REFRESH_RATE; |
| import static com.android.internal.display.RefreshRateSettingsUtils.findHighestRefreshRateAmongAllDisplays; |
| import static com.android.internal.display.RefreshRateSettingsUtils.findHighestRefreshRateForDefaultDisplay; |
| |
| 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 androidx.annotation.VisibleForTesting; |
| import androidx.preference.Preference; |
| import androidx.preference.PreferenceScreen; |
| |
| import com.android.server.display.feature.flags.Flags; |
| import com.android.settings.R; |
| import com.android.settings.core.TogglePreferenceController; |
| 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.concurrent.Executor; |
| |
| public class PeakRefreshRatePreferenceController extends TogglePreferenceController |
| implements LifecycleObserver, OnStart, OnStop { |
| |
| @VisibleForTesting float mPeakRefreshRate; |
| |
| private static final String TAG = "RefreshRatePrefCtr"; |
| private static final float INVALIDATE_REFRESH_RATE = -1f; |
| |
| private final Handler mHandler; |
| private final IDeviceConfigChange mOnDeviceConfigChange; |
| private DeviceConfigDisplaySettings mDeviceConfigDisplaySettings; |
| private Preference mPreference; |
| |
| private interface IDeviceConfigChange { |
| void onDefaultRefreshRateChanged(); |
| } |
| |
| public PeakRefreshRatePreferenceController(Context context, String key) { |
| super(context, key); |
| mHandler = new Handler(context.getMainLooper()); |
| mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings(); |
| mOnDeviceConfigChange = |
| new IDeviceConfigChange() { |
| public void onDefaultRefreshRateChanged() { |
| updateState(mPreference); |
| } |
| }; |
| mPeakRefreshRate = Math.round(Flags.backUpSmoothDisplayAndForcePeakRefreshRate() |
| ? findHighestRefreshRateAmongAllDisplays(context) |
| : findHighestRefreshRateForDefaultDisplay(context)); |
| Log.d( |
| TAG, |
| "DEFAULT_REFRESH_RATE : " |
| + DEFAULT_REFRESH_RATE |
| + " mPeakRefreshRate : " |
| + mPeakRefreshRate); |
| } |
| |
| @Override |
| public void displayPreference(PreferenceScreen screen) { |
| super.displayPreference(screen); |
| |
| int defaultPeakRefreshRate = Math.round(mPeakRefreshRate); |
| |
| mPreference = screen.findPreference(getPreferenceKey()); |
| mPreference.setSummary(mContext.getString( |
| R.string.peak_refresh_rate_summary, defaultPeakRefreshRate)); |
| } |
| |
| @Override |
| public int getAvailabilityStatus() { |
| if (mContext.getResources().getBoolean(R.bool.config_show_smooth_display)) { |
| return mPeakRefreshRate > DEFAULT_REFRESH_RATE ? AVAILABLE : UNSUPPORTED_ON_DEVICE; |
| } else { |
| return UNSUPPORTED_ON_DEVICE; |
| } |
| } |
| |
| @Override |
| public boolean isChecked() { |
| final float peakRefreshRate = |
| Settings.System.getFloat( |
| mContext.getContentResolver(), |
| Settings.System.PEAK_REFRESH_RATE, |
| getDefaultPeakRefreshRate()); |
| return Math.round(peakRefreshRate) == Math.round(mPeakRefreshRate) |
| || Float.isInfinite(peakRefreshRate); |
| } |
| |
| @Override |
| public boolean setChecked(boolean isChecked) { |
| final float valueIfChecked = Flags.backUpSmoothDisplayAndForcePeakRefreshRate() |
| ? Float.POSITIVE_INFINITY : mPeakRefreshRate; |
| final float peakRefreshRate = isChecked ? valueIfChecked : DEFAULT_REFRESH_RATE; |
| Log.d(TAG, "setChecked to : " + peakRefreshRate); |
| |
| return Settings.System.putFloat( |
| mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE, peakRefreshRate); |
| } |
| |
| @Override |
| public int getSliceHighlightMenuRes() { |
| return R.string.menu_key_display; |
| } |
| |
| @Override |
| public void onStart() { |
| mDeviceConfigDisplaySettings.startListening(); |
| } |
| |
| @Override |
| public void onStop() { |
| mDeviceConfigDisplaySettings.stopListening(); |
| } |
| |
| @VisibleForTesting |
| void injectDeviceConfigDisplaySettings( |
| DeviceConfigDisplaySettings deviceConfigDisplaySettings) { |
| mDeviceConfigDisplaySettings = deviceConfigDisplaySettings; |
| } |
| |
| @VisibleForTesting |
| 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(mPreference); |
| } |
| } |
| |
| @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); |
| } |
| |
| Log.d(TAG, "DeviceConfig getDefaultPeakRefreshRate : " + defaultPeakRefreshRate); |
| return defaultPeakRefreshRate; |
| } |
| } |