summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLong Ling <longling@google.com>2019-08-20 15:01:14 -0700
committerandroid-build-team Robot <android-build-team-robot@google.com>2019-09-20 04:39:40 +0000
commit35d2ef154a27e51b0f1d7a0585dd601203278bdd (patch)
tree04ad2333f8b6e5601535f64b8c45773f6df17029
parenta53703f44a8cb453397633e43fbac7e4bfa3d95e (diff)
downloadbase-35d2ef154a27e51b0f1d7a0585dd601203278bdd.tar.gz
DMD: Support 90hz only in the refresh rate zone
Also allow DeviceConfig to change the zone behavior to 60 Hz only. Change BrightObserver priority to be the lowest so application request won't be overriden by BrightnessObserver Bug: 139487676 Change-Id: I959550350c1ea72f764984226350ebc6e7de591c (cherry picked from commit 73936631d57b4626ba0a389065e2dabcaf0daa79)
-rw-r--r--core/java/android/hardware/display/DisplayManager.java23
-rw-r--r--core/res/res/values/config.xml4
-rw-r--r--core/res/res/values/symbols.xml1
-rw-r--r--services/core/java/com/android/server/display/DisplayModeDirector.java128
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 5d8fa92263c4..0b25dbd78611 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 97fd02f53513..500a24282191 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;
@@ -816,6 +848,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();
@@ -825,6 +858,8 @@ public class DisplayModeDirector {
mDisplayBrightnessThresholds = brightnessThresholds;
mAmbientBrightnessThresholds = ambientThresholds;
}
+
+ mRefreshRateInZone = mDeviceConfigDisplaySettings.getRefreshRateInZone();
restartObserver();
mDeviceConfigDisplaySettings.startListening();
}
@@ -864,8 +899,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);
@@ -952,6 +995,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;
@@ -961,37 +1008,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);
}
@@ -1133,7 +1185,6 @@ public class DisplayModeDirector {
}
private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener {
-
public DeviceConfigDisplaySettings() {
}
@@ -1147,7 +1198,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);
}
/*
@@ -1155,7 +1207,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);
}
/*
@@ -1172,17 +1225,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) {