diff options
| -rw-r--r-- | core/java/android/hardware/display/DisplayManager.java | 23 | ||||
| -rw-r--r-- | core/res/res/values/config.xml | 4 | ||||
| -rw-r--r-- | core/res/res/values/symbols.xml | 1 | ||||
| -rw-r--r-- | services/core/java/com/android/server/display/DisplayModeDirector.java | 128 |
4 files changed, 121 insertions, 35 deletions
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java index 21c49add6cba..bf794731c6b4 100644 --- a/core/java/android/hardware/display/DisplayManager.java +++ b/core/java/android/hardware/display/DisplayManager.java @@ -829,23 +829,36 @@ public final class DisplayManager { public interface DeviceConfig { /** - * Key for accessing the 60 hz only regions. + * Key for refresh rate in the zone defined by thresholds. + * + * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER + * @see android.R.integer#config_defaultZoneBehavior + */ + String KEY_REFRESH_RATE_IN_ZONE = "refresh_rate_in_zone"; + + /** + * Key for accessing the display brightness thresholds for the configured refresh rate zone. + * The value will be a pair of comma separated integers representing the minimum and maximum + * thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]). * * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate * @hide */ - String KEY_PEAK_REFRESH_RATE_BRIGHTNESS_THRESHOLDS = + String KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS = "peak_refresh_rate_brightness_thresholds"; /** - * Key for accessing the 60 hz only regions. + * Key for accessing the ambient brightness thresholds for the configured refresh rate zone. + * The value will be a pair of comma separated integers representing the minimum and maximum + * thresholds of the zone, respectively, in lux. * * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER - * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate + * @see android.R.array#config_ambientThresholdsOfPeakRefreshRate * @hide */ - String KEY_PEAK_REFRESH_RATE_AMBIENT_THRESHOLDS = "peak_refresh_rate_ambient_thresholds"; + String KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS = + "peak_refresh_rate_ambient_thresholds"; /** * Key for default peak refresh rate diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index df879816facb..1577a227ff67 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -4167,6 +4167,10 @@ --> </integer-array> + <!-- Default refresh rate in the zone defined by brightness and ambient thresholds. + If non-positive, then the refresh rate is unchanged even if thresholds are configured. --> + <integer name="config_defaultRefreshRateInZone">0</integer> + <!-- The type of the light sensor to be used by the display framework for things like auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. --> <string name="config_displayLightSensorType" translatable="false" /> diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 92c5d2cf88df..0d9c4b39fea0 100644 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -3791,6 +3791,7 @@ <!-- For high refresh rate displays --> <java-symbol type="integer" name="config_defaultPeakRefreshRate" /> + <java-symbol type="integer" name="config_defaultRefreshRateInZone" /> <java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" /> <java-symbol type="array" name="config_ambientThresholdsOfPeakRefreshRate" /> diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java index 58aadd1cbef4..1fc0db3ff7cb 100644 --- a/services/core/java/com/android/server/display/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/DisplayModeDirector.java @@ -69,6 +69,7 @@ public class DisplayModeDirector { private static final int MSG_ALLOWED_MODES_CHANGED = 1; private static final int MSG_BRIGHTNESS_THRESHOLDS_CHANGED = 2; private static final int MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED = 3; + private static final int MSG_REFRESH_RATE_IN_ZONE_CHANGED = 4; // Special ID used to indicate that given vote is to be applied globally, rather than to a // specific display. @@ -440,23 +441,48 @@ public class DisplayModeDirector { mSettingsObserver.onDeviceConfigDefaultPeakRefreshRateChanged( defaultPeakRefreshRate); break; + + case MSG_REFRESH_RATE_IN_ZONE_CHANGED: + int refreshRateInZone = msg.arg1; + mBrightnessObserver.onDeviceConfigRefreshRateInZoneChanged( + refreshRateInZone); + break; } } } private static final class Vote { - // We split the app request into two priorities in case we can satisfy one desire without - // the other. - public static final int PRIORITY_APP_REQUEST_REFRESH_RATE = 0; - public static final int PRIORITY_APP_REQUEST_SIZE = 1; - public static final int PRIORITY_USER_SETTING_REFRESH_RATE = 2; - public static final int PRIORITY_LOW_BRIGHTNESS = 3; - public static final int PRIORITY_LOW_POWER_MODE = 4; + // LOW_BRIGHTNESS votes for a single refresh rate like [60,60], [90,90] or null. + // If the higher voters result is a range, it will fix the rate to a single choice. + // It's used to avoid rate switch in certain conditions. + public static final int PRIORITY_LOW_BRIGHTNESS = 0; + + // SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate. + // It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY] + public static final int PRIORITY_USER_SETTING_MIN_REFRESH_RATE = 1; + + // We split the app request into different priorities in case we can satisfy one desire + // without the other. + + // Application can specify preferred refresh rate with below attrs. + // @see android.view.WindowManager.LayoutParams#preferredRefreshRate + // @see android.view.WindowManager.LayoutParams#preferredDisplayModeId + // System also forces some apps like blacklisted app to run at a lower refresh rate. + // @see android.R.array#config_highRefreshRateBlacklist + public static final int PRIORITY_APP_REQUEST_REFRESH_RATE = 2; + public static final int PRIORITY_APP_REQUEST_SIZE = 3; + + // SETTING_PEAK_REFRESH_RATE has a high priority and will restrict the bounds of the rest + // of low priority voters. It votes [0, max(PEAK, MIN)] + public static final int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 4; + + // LOW_POWER_MODE force display to [0, 60HZ] if Settings.Global.LOW_POWER_MODE is on. + public static final int PRIORITY_LOW_POWER_MODE = 5; // Whenever a new priority is added, remember to update MIN_PRIORITY and/or MAX_PRIORITY as // appropriate, as well as priorityToString. - public static final int MIN_PRIORITY = PRIORITY_APP_REQUEST_REFRESH_RATE; + public static final int MIN_PRIORITY = PRIORITY_LOW_BRIGHTNESS; public static final int MAX_PRIORITY = PRIORITY_LOW_POWER_MODE; /** @@ -500,12 +526,16 @@ public class DisplayModeDirector { public static String priorityToString(int priority) { switch (priority) { + case PRIORITY_LOW_BRIGHTNESS: + return "PRIORITY_LOW_BRIGHTNESS"; + case PRIORITY_USER_SETTING_MIN_REFRESH_RATE: + return "PRIORITY_USER_SETTING_MIN_REFRESH_RATE"; case PRIORITY_APP_REQUEST_REFRESH_RATE: return "PRIORITY_APP_REQUEST_REFRESH_RATE"; case PRIORITY_APP_REQUEST_SIZE: return "PRIORITY_APP_REQUEST_SIZE"; - case PRIORITY_USER_SETTING_REFRESH_RATE: - return "PRIORITY_USER_SETTING_REFRESH_RATE"; + case PRIORITY_USER_SETTING_PEAK_REFRESH_RATE: + return "PRIORITY_USER_SETTING_PEAK_REFRESH_RATE"; case PRIORITY_LOW_POWER_MODE: return "PRIORITY_LOW_POWER_MODE"; default: @@ -608,12 +638,11 @@ public class DisplayModeDirector { float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(), Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate); - if (peakRefreshRate < minRefreshRate) { - peakRefreshRate = minRefreshRate; - } + updateVoteLocked(Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE, + Vote.forRefreshRates(0f, Math.max(minRefreshRate, peakRefreshRate))); + updateVoteLocked(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE, + Vote.forRefreshRates(minRefreshRate, Float.POSITIVE_INFINITY)); - Vote vote = Vote.forRefreshRates(minRefreshRate, peakRefreshRate); - updateVoteLocked(Vote.PRIORITY_USER_SETTING_REFRESH_RATE, vote); mBrightnessObserver.onRefreshRateSettingChangedLocked(minRefreshRate, peakRefreshRate); } @@ -655,6 +684,7 @@ public class DisplayModeDirector { refreshRateVote = null; sizeVote = null; } + updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, refreshRateVote); updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_SIZE, sizeVote); return; @@ -799,6 +829,8 @@ public class DisplayModeDirector { private boolean mRefreshRateChangeable = false; private boolean mLowPowerModeEnabled = false; + private int mRefreshRateInZone; + BrightnessObserver(Context context, Handler handler) { super(handler); mContext = context; @@ -815,6 +847,7 @@ public class DisplayModeDirector { public void observe(SensorManager sensorManager) { mSensorManager = sensorManager; + // DeviceConfig is accessible after system ready. int[] brightnessThresholds = mDeviceConfigDisplaySettings.getBrightnessThresholds(); int[] ambientThresholds = mDeviceConfigDisplaySettings.getAmbientThresholds(); @@ -824,6 +857,8 @@ public class DisplayModeDirector { mDisplayBrightnessThresholds = brightnessThresholds; mAmbientBrightnessThresholds = ambientThresholds; } + + mRefreshRateInZone = mDeviceConfigDisplaySettings.getRefreshRateInZone(); restartObserver(); mDeviceConfigDisplaySettings.startListening(); } @@ -863,8 +898,16 @@ public class DisplayModeDirector { restartObserver(); } + public void onDeviceConfigRefreshRateInZoneChanged(int refreshRate) { + if (refreshRate != mRefreshRateInZone) { + mRefreshRateInZone = refreshRate; + restartObserver(); + } + } + public void dumpLocked(PrintWriter pw) { pw.println(" BrightnessObserver"); + pw.println(" mRefreshRateInZone: " + mRefreshRateInZone); for (int d: mDisplayBrightnessThresholds) { pw.println(" mDisplayBrightnessThreshold: " + d); @@ -950,6 +993,10 @@ public class DisplayModeDirector { * to value changes. */ private boolean checkShouldObserve(int[] a) { + if (mRefreshRateInZone <= 0) { + return false; + } + for (int d: a) { if (d >= 0) { return true; @@ -959,37 +1006,42 @@ public class DisplayModeDirector { return false; } - private void onBrightnessChangedLocked() { - int brightness = Settings.System.getInt(mContext.getContentResolver(), - Settings.System.SCREEN_BRIGHTNESS, -1); - - Vote vote = null; + private boolean isInsideZone(int brightness, float lux) { for (int i = 0; i < mDisplayBrightnessThresholds.length; i++) { int disp = mDisplayBrightnessThresholds[i]; int ambi = mAmbientBrightnessThresholds[i]; if (disp >= 0 && ambi >= 0) { if (brightness <= disp && mAmbientLux <= ambi) { - vote = Vote.forRefreshRates(0f, 60f); + return true; } } else if (disp >= 0) { if (brightness <= disp) { - vote = Vote.forRefreshRates(0f, 60f); + return true; } } else if (ambi >= 0) { if (mAmbientLux <= ambi) { - vote = Vote.forRefreshRates(0f, 60f); + return true; } } + } - if (vote != null) { - break; - } + return false; + } + + private void onBrightnessChangedLocked() { + int brightness = Settings.System.getInt(mContext.getContentResolver(), + Settings.System.SCREEN_BRIGHTNESS, -1); + + Vote vote = null; + boolean insideZone = isInsideZone(brightness, mAmbientLux); + if (insideZone) { + vote = Vote.forRefreshRates(mRefreshRateInZone, mRefreshRateInZone); } if (DEBUG) { Slog.d(TAG, "Display brightness " + brightness + ", ambient lux " + mAmbientLux + - (vote != null ? " 60hz only" : " no refresh rate limit")); + ", Vote " + vote); } updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, vote); } @@ -1104,7 +1156,6 @@ public class DisplayModeDirector { } private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener { - public DeviceConfigDisplaySettings() { } @@ -1118,7 +1169,8 @@ public class DisplayModeDirector { */ public int[] getBrightnessThresholds() { return getIntArrayProperty( - DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_BRIGHTNESS_THRESHOLDS); + DisplayManager.DeviceConfig. + KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS); } /* @@ -1126,7 +1178,8 @@ public class DisplayModeDirector { */ public int[] getAmbientThresholds() { return getIntArrayProperty( - DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_AMBIENT_THRESHOLDS); + DisplayManager.DeviceConfig. + KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS); } /* @@ -1143,17 +1196,32 @@ public class DisplayModeDirector { return defaultPeakRefreshRate; } + public int getRefreshRateInZone() { + int defaultRefreshRateInZone = mContext.getResources().getInteger( + R.integer.config_defaultRefreshRateInZone); + + int refreshRate = DeviceConfig.getInt( + DeviceConfig.NAMESPACE_DISPLAY_MANAGER, + DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_ZONE, + defaultRefreshRateInZone); + + return refreshRate; + } + @Override public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) { int[] brightnessThresholds = getBrightnessThresholds(); int[] ambientThresholds = getAmbientThresholds(); Float defaultPeakRefreshRate = getDefaultPeakRefreshRate(); + int refreshRateInZone = getRefreshRateInZone(); mHandler.obtainMessage(MSG_BRIGHTNESS_THRESHOLDS_CHANGED, new Pair<int[], int[]>(brightnessThresholds, ambientThresholds)) .sendToTarget(); mHandler.obtainMessage(MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED, defaultPeakRefreshRate).sendToTarget(); + mHandler.obtainMessage(MSG_REFRESH_RATE_IN_ZONE_CHANGED, refreshRateInZone, + 0).sendToTarget(); } private int[] getIntArrayProperty(String prop) { |