summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Ady Abraham <adyabr@google.com> 2022-10-24 17:46:26 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-10-24 17:46:26 +0000
commit1ff67245399dbb6ed19f926b6eeb25995577d00c (patch)
treeb7556e3a54e3f8f0aaa263a872477f5413803685
parent5dc888399c4e6bc976f0862b273dd8dec32082de (diff)
parentb878a206e8fb976f7ca8b2969a5c2ddb4fc24cc3 (diff)
Merge "DisplayModeDirector: separate the display refresh rate and the render frame rate"
-rw-r--r--core/java/android/hardware/display/DisplayManagerInternal.java69
-rw-r--r--core/java/android/view/SurfaceControl.java214
-rw-r--r--core/jni/android_view_SurfaceControl.cpp158
-rw-r--r--services/core/java/com/android/server/display/DisplayManagerService.java1
-rw-r--r--services/core/java/com/android/server/display/DisplayModeDirector.java400
-rw-r--r--services/core/java/com/android/server/display/LocalDisplayAdapter.java16
-rw-r--r--services/core/java/com/android/server/wm/RefreshRatePolicy.java2
-rw-r--r--services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java31
-rw-r--r--services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java982
9 files changed, 1329 insertions, 544 deletions
diff --git a/core/java/android/hardware/display/DisplayManagerInternal.java b/core/java/android/hardware/display/DisplayManagerInternal.java
index 00bccc686919..6b3e67309f22 100644
--- a/core/java/android/hardware/display/DisplayManagerInternal.java
+++ b/core/java/android/hardware/display/DisplayManagerInternal.java
@@ -24,11 +24,11 @@ import android.hardware.SensorManager;
import android.os.Handler;
import android.os.PowerManager;
import android.util.IntArray;
-import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
import android.view.DisplayInfo;
import android.view.SurfaceControl;
+import android.view.SurfaceControl.RefreshRateRange;
import android.view.SurfaceControl.Transaction;
import android.window.DisplayWindowPolicyController;
import android.window.ScreenCapture;
@@ -36,7 +36,6 @@ import android.window.ScreenCapture;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
-import java.util.Objects;
import java.util.Set;
/**
@@ -651,72 +650,6 @@ public abstract class DisplayManagerInternal {
}
/**
- * Information about the min and max refresh rate DM would like to set the display to.
- */
- public static final class RefreshRateRange {
- public static final String TAG = "RefreshRateRange";
-
- // The tolerance within which we consider something approximately equals.
- public static final float FLOAT_TOLERANCE = 0.01f;
-
- /**
- * The lowest desired refresh rate.
- */
- public float min;
-
- /**
- * The highest desired refresh rate.
- */
- public float max;
-
- public RefreshRateRange() {}
-
- public RefreshRateRange(float min, float max) {
- if (min < 0 || max < 0 || min > max + FLOAT_TOLERANCE) {
- Slog.e(TAG, "Wrong values for min and max when initializing RefreshRateRange : "
- + min + " " + max);
- this.min = this.max = 0;
- return;
- }
- if (min > max) {
- // Min and max are within epsilon of each other, but in the wrong order.
- float t = min;
- min = max;
- max = t;
- }
- this.min = min;
- this.max = max;
- }
-
- /**
- * Checks whether the two objects have the same values.
- */
- @Override
- public boolean equals(Object other) {
- if (other == this) {
- return true;
- }
-
- if (!(other instanceof RefreshRateRange)) {
- return false;
- }
-
- RefreshRateRange refreshRateRange = (RefreshRateRange) other;
- return (min == refreshRateRange.min && max == refreshRateRange.max);
- }
-
- @Override
- public int hashCode() {
- return Objects.hash(min, max);
- }
-
- @Override
- public String toString() {
- return "(" + min + " " + max + ")";
- }
- }
-
- /**
* Describes a limitation on a display's refresh rate. Includes the allowed refresh rate
* range as well as information about when it applies, such as high-brightness-mode.
*/
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index c46f33a4a786..06851de95f82 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -67,6 +67,7 @@ import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.ArrayMap;
import android.util.Log;
+import android.util.Slog;
import android.util.SparseIntArray;
import android.util.proto.ProtoOutputStream;
import android.view.Surface.OutOfResourcesException;
@@ -1673,6 +1674,146 @@ public final class SurfaceControl implements Parcelable {
return nativeGetDisplayedContentSample(displayToken, maxFrames, timestamp);
}
+ /**
+ * Information about the min and max refresh rate DM would like to set the display to.
+ * @hide
+ */
+ public static final class RefreshRateRange {
+ public static final String TAG = "RefreshRateRange";
+
+ // The tolerance within which we consider something approximately equals.
+ public static final float FLOAT_TOLERANCE = 0.01f;
+
+ /**
+ * The lowest desired refresh rate.
+ */
+ public float min;
+
+ /**
+ * The highest desired refresh rate.
+ */
+ public float max;
+
+ public RefreshRateRange() {}
+
+ public RefreshRateRange(float min, float max) {
+ if (min < 0 || max < 0 || min > max + FLOAT_TOLERANCE) {
+ Slog.e(TAG, "Wrong values for min and max when initializing RefreshRateRange : "
+ + min + " " + max);
+ this.min = this.max = 0;
+ return;
+ }
+ if (min > max) {
+ // Min and max are within epsilon of each other, but in the wrong order.
+ float t = min;
+ min = max;
+ max = t;
+ }
+ this.min = min;
+ this.max = max;
+ }
+
+ /**
+ * Checks whether the two objects have the same values.
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ if (!(other instanceof RefreshRateRange)) {
+ return false;
+ }
+
+ RefreshRateRange refreshRateRange = (RefreshRateRange) other;
+ return (min == refreshRateRange.min && max == refreshRateRange.max);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(min, max);
+ }
+
+ @Override
+ public String toString() {
+ return "(" + min + " " + max + ")";
+ }
+
+ /**
+ * Copies the supplied object's values to this object.
+ */
+ public void copyFrom(RefreshRateRange other) {
+ this.min = other.min;
+ this.max = other.max;
+ }
+ }
+
+ /**
+ * Information about the ranges of refresh rates for the display physical refresh rates and the
+ * render frame rate DM would like to set the policy to.
+ * @hide
+ */
+ public static final class RefreshRateRanges {
+ public static final String TAG = "RefreshRateRanges";
+
+ /**
+ * The range of refresh rates that the display should run at.
+ */
+ public final RefreshRateRange physical;
+
+ /**
+ * The range of refresh rates that apps should render at.
+ */
+ public final RefreshRateRange render;
+
+ public RefreshRateRanges() {
+ physical = new RefreshRateRange();
+ render = new RefreshRateRange();
+ }
+
+ public RefreshRateRanges(RefreshRateRange physical, RefreshRateRange render) {
+ this.physical = new RefreshRateRange(physical.min, physical.max);
+ this.render = new RefreshRateRange(render.min, render.max);
+ }
+
+ /**
+ * Checks whether the two objects have the same values.
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other == this) {
+ return true;
+ }
+
+ if (!(other instanceof RefreshRateRanges)) {
+ return false;
+ }
+
+ RefreshRateRanges rates = (RefreshRateRanges) other;
+ return physical.equals(rates.physical) && render.equals(
+ rates.render);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(physical, render);
+ }
+
+ @Override
+ public String toString() {
+ return "physical: " + physical + " render: " + render;
+ }
+
+ /**
+ * Copies the supplied object's values to this object.
+ */
+ public void copyFrom(RefreshRateRanges other) {
+ this.physical.copyFrom(other.physical);
+ this.render.copyFrom(other.render);
+ }
+ }
+
/**
* Contains information about desired display configuration.
@@ -1682,44 +1823,49 @@ public final class SurfaceControl implements Parcelable {
public static final class DesiredDisplayModeSpecs {
public int defaultMode;
/**
- * The primary refresh rate range represents display manager's general guidance on the
- * display configs surface flinger will consider when switching refresh rates. Unless
- * surface flinger has a specific reason to do otherwise, it will stay within this range.
+ * If true this will allow switching between modes in different display configuration
+ * groups. This way the user may see visual interruptions when the display mode changes.
*/
- public float primaryRefreshRateMin;
- public float primaryRefreshRateMax;
+ public boolean allowGroupSwitching;
+
/**
- * The app request refresh rate range allows surface flinger to consider more display
- * configs when switching refresh rates. Although surface flinger will generally stay within
- * the primary range, specific considerations, such as layer frame rate settings specified
- * via the setFrameRate() api, may cause surface flinger to go outside the primary
- * range. Surface flinger never goes outside the app request range. The app request range
- * will be greater than or equal to the primary refresh rate range, never smaller.
+ * The primary physical and render refresh rate ranges represent display manager's general
+ * guidance on the display configs surface flinger will consider when switching refresh
+ * rates and scheduling the frame rate. Unless surface flinger has a specific reason to do
+ * otherwise, it will stay within this range.
*/
- public float appRequestRefreshRateMin;
- public float appRequestRefreshRateMax;
+ public final RefreshRateRanges primaryRanges;
/**
- * If true this will allow switching between modes in different display configuration
- * groups. This way the user may see visual interruptions when the display mode changes.
+ * The app request physical and render refresh rate ranges allow surface flinger to consider
+ * more display configs when switching refresh rates. Although surface flinger will
+ * generally stay within the primary range, specific considerations, such as layer frame
+ * rate settings specified via the setFrameRate() api, may cause surface flinger to go
+ * outside the primary range. Surface flinger never goes outside the app request range.
+ * The app request range will be greater than or equal to the primary refresh rate range,
+ * never smaller.
*/
- public boolean allowGroupSwitching;
+ public final RefreshRateRanges appRequestRanges;
- public DesiredDisplayModeSpecs() {}
+ public DesiredDisplayModeSpecs() {
+ this.primaryRanges = new RefreshRateRanges();
+ this.appRequestRanges = new RefreshRateRanges();
+ }
public DesiredDisplayModeSpecs(DesiredDisplayModeSpecs other) {
+ this.primaryRanges = new RefreshRateRanges();
+ this.appRequestRanges = new RefreshRateRanges();
copyFrom(other);
}
public DesiredDisplayModeSpecs(int defaultMode, boolean allowGroupSwitching,
- float primaryRefreshRateMin, float primaryRefreshRateMax,
- float appRequestRefreshRateMin, float appRequestRefreshRateMax) {
+ RefreshRateRanges primaryRanges, RefreshRateRanges appRequestRanges) {
this.defaultMode = defaultMode;
this.allowGroupSwitching = allowGroupSwitching;
- this.primaryRefreshRateMin = primaryRefreshRateMin;
- this.primaryRefreshRateMax = primaryRefreshRateMax;
- this.appRequestRefreshRateMin = appRequestRefreshRateMin;
- this.appRequestRefreshRateMax = appRequestRefreshRateMax;
+ this.primaryRanges =
+ new RefreshRateRanges(primaryRanges.physical, primaryRanges.render);
+ this.appRequestRanges =
+ new RefreshRateRanges(appRequestRanges.physical, appRequestRanges.render);
}
@Override
@@ -1732,10 +1878,9 @@ public final class SurfaceControl implements Parcelable {
*/
public boolean equals(DesiredDisplayModeSpecs other) {
return other != null && defaultMode == other.defaultMode
- && primaryRefreshRateMin == other.primaryRefreshRateMin
- && primaryRefreshRateMax == other.primaryRefreshRateMax
- && appRequestRefreshRateMin == other.appRequestRefreshRateMin
- && appRequestRefreshRateMax == other.appRequestRefreshRateMax;
+ && allowGroupSwitching == other.allowGroupSwitching
+ && primaryRanges.equals(other.primaryRanges)
+ && appRequestRanges.equals(other.appRequestRanges);
}
@Override
@@ -1748,18 +1893,17 @@ public final class SurfaceControl implements Parcelable {
*/
public void copyFrom(DesiredDisplayModeSpecs other) {
defaultMode = other.defaultMode;
- primaryRefreshRateMin = other.primaryRefreshRateMin;
- primaryRefreshRateMax = other.primaryRefreshRateMax;
- appRequestRefreshRateMin = other.appRequestRefreshRateMin;
- appRequestRefreshRateMax = other.appRequestRefreshRateMax;
+ allowGroupSwitching = other.allowGroupSwitching;
+ primaryRanges.copyFrom(other.primaryRanges);
+ appRequestRanges.copyFrom(other.appRequestRanges);
}
@Override
public String toString() {
- return String.format("defaultConfig=%d primaryRefreshRateRange=[%.0f %.0f]"
- + " appRequestRefreshRateRange=[%.0f %.0f]",
- defaultMode, primaryRefreshRateMin, primaryRefreshRateMax,
- appRequestRefreshRateMin, appRequestRefreshRateMax);
+ return "defaultMode=" + defaultMode
+ + " allowGroupSwitching=" + allowGroupSwitching
+ + " primaryRanges=" + primaryRanges
+ + " appRequestRanges=" + appRequestRanges;
}
}
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index e36815c4beb9..8fd040189f8b 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -190,12 +190,24 @@ static struct {
static struct {
jclass clazz;
jmethodID ctor;
+ jfieldID min;
+ jfieldID max;
+} gRefreshRateRangeClassInfo;
+
+static struct {
+ jclass clazz;
+ jmethodID ctor;
+ jfieldID physical;
+ jfieldID render;
+} gRefreshRateRangesClassInfo;
+
+static struct {
+ jclass clazz;
+ jmethodID ctor;
jfieldID defaultMode;
jfieldID allowGroupSwitching;
- jfieldID primaryRefreshRateMin;
- jfieldID primaryRefreshRateMax;
- jfieldID appRequestRefreshRateMin;
- jfieldID appRequestRefreshRateMax;
+ jfieldID primaryRanges;
+ jfieldID appRequestRanges;
} gDesiredDisplayModeSpecsClassInfo;
static struct {
@@ -1190,6 +1202,39 @@ static jobject nativeGetDynamicDisplayInfo(JNIEnv* env, jclass clazz, jobject to
return object;
}
+struct RefreshRateRange {
+ const float min;
+ const float max;
+
+ RefreshRateRange(float min, float max) : min(min), max(max) {}
+
+ RefreshRateRange(JNIEnv* env, jobject obj)
+ : min(env->GetFloatField(obj, gRefreshRateRangeClassInfo.min)),
+ max(env->GetFloatField(obj, gRefreshRateRangeClassInfo.max)) {}
+
+ jobject toJava(JNIEnv* env) const {
+ return env->NewObject(gRefreshRateRangeClassInfo.clazz, gRefreshRateRangeClassInfo.ctor,
+ min, max);
+ }
+};
+
+struct RefreshRateRanges {
+ const RefreshRateRange physical;
+ const RefreshRateRange render;
+
+ RefreshRateRanges(RefreshRateRange physical, RefreshRateRange render)
+ : physical(physical), render(render) {}
+
+ RefreshRateRanges(JNIEnv* env, jobject obj)
+ : physical(env, env->GetObjectField(obj, gRefreshRateRangesClassInfo.physical)),
+ render(env, env->GetObjectField(obj, gRefreshRateRangesClassInfo.render)) {}
+
+ jobject toJava(JNIEnv* env) const {
+ return env->NewObject(gRefreshRateRangesClassInfo.clazz, gRefreshRateRangesClassInfo.ctor,
+ physical.toJava(env), render.toJava(env));
+ }
+};
+
static jboolean nativeSetDesiredDisplayModeSpecs(JNIEnv* env, jclass clazz, jobject tokenObj,
jobject DesiredDisplayModeSpecs) {
sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
@@ -1200,25 +1245,23 @@ static jboolean nativeSetDesiredDisplayModeSpecs(JNIEnv* env, jclass clazz, jobj
jboolean allowGroupSwitching =
env->GetBooleanField(DesiredDisplayModeSpecs,
gDesiredDisplayModeSpecsClassInfo.allowGroupSwitching);
- jfloat primaryRefreshRateMin =
- env->GetFloatField(DesiredDisplayModeSpecs,
- gDesiredDisplayModeSpecsClassInfo.primaryRefreshRateMin);
- jfloat primaryRefreshRateMax =
- env->GetFloatField(DesiredDisplayModeSpecs,
- gDesiredDisplayModeSpecsClassInfo.primaryRefreshRateMax);
- jfloat appRequestRefreshRateMin =
- env->GetFloatField(DesiredDisplayModeSpecs,
- gDesiredDisplayModeSpecsClassInfo.appRequestRefreshRateMin);
- jfloat appRequestRefreshRateMax =
- env->GetFloatField(DesiredDisplayModeSpecs,
- gDesiredDisplayModeSpecsClassInfo.appRequestRefreshRateMax);
-
- size_t result = SurfaceComposerClient::setDesiredDisplayModeSpecs(token, defaultMode,
- allowGroupSwitching,
- primaryRefreshRateMin,
- primaryRefreshRateMax,
- appRequestRefreshRateMin,
- appRequestRefreshRateMax);
+
+ const jobject primaryRangesObject =
+ env->GetObjectField(DesiredDisplayModeSpecs,
+ gDesiredDisplayModeSpecsClassInfo.primaryRanges);
+ const jobject appRequestRangesObject =
+ env->GetObjectField(DesiredDisplayModeSpecs,
+ gDesiredDisplayModeSpecsClassInfo.appRequestRanges);
+ const RefreshRateRanges primaryRanges(env, primaryRangesObject);
+ const RefreshRateRanges appRequestRanges(env, appRequestRangesObject);
+
+ size_t result =
+ SurfaceComposerClient::setDesiredDisplayModeSpecs(token, defaultMode,
+ allowGroupSwitching,
+ primaryRanges.physical.min,
+ primaryRanges.physical.max,
+ appRequestRanges.physical.min,
+ appRequestRanges.physical.max);
return result == NO_ERROR ? JNI_TRUE : JNI_FALSE;
}
@@ -1228,22 +1271,31 @@ static jobject nativeGetDesiredDisplayModeSpecs(JNIEnv* env, jclass clazz, jobje
ui::DisplayModeId defaultMode;
bool allowGroupSwitching;
- float primaryRefreshRateMin;
- float primaryRefreshRateMax;
- float appRequestRefreshRateMin;
- float appRequestRefreshRateMax;
+ float primaryPhysicalRefreshRateMin;
+ float primaryPhysicalRefreshRateMax;
+ float appRequestPhysicalRefreshRateMin;
+ float appRequestPhysicalRefreshRateMax;
if (SurfaceComposerClient::getDesiredDisplayModeSpecs(token, &defaultMode, &allowGroupSwitching,
- &primaryRefreshRateMin,
- &primaryRefreshRateMax,
- &appRequestRefreshRateMin,
- &appRequestRefreshRateMax) != NO_ERROR) {
+ &primaryPhysicalRefreshRateMin,
+ &primaryPhysicalRefreshRateMax,
+ &appRequestPhysicalRefreshRateMin,
+ &appRequestPhysicalRefreshRateMax) !=
+ NO_ERROR) {
return nullptr;
}
+ const RefreshRateRange primaryPhysicalRange(primaryPhysicalRefreshRateMin,
+ primaryPhysicalRefreshRateMax);
+ const RefreshRateRange appRequestPhysicalRange(appRequestPhysicalRefreshRateMin,
+ appRequestPhysicalRefreshRateMax);
+
+ // TODO(b/241460058): populate the render ranges
+ const RefreshRateRanges primaryRanges(primaryPhysicalRange, primaryPhysicalRange);
+ const RefreshRateRanges appRequestRanges(appRequestPhysicalRange, appRequestPhysicalRange);
+
return env->NewObject(gDesiredDisplayModeSpecsClassInfo.clazz,
gDesiredDisplayModeSpecsClassInfo.ctor, defaultMode, allowGroupSwitching,
- primaryRefreshRateMin, primaryRefreshRateMax, appRequestRefreshRateMin,
- appRequestRefreshRateMax);
+ primaryRanges.toJava(env), appRequestRanges.toJava(env));
}
static jobject nativeGetDisplayNativePrimaries(JNIEnv* env, jclass, jobject tokenObj) {
@@ -2235,23 +2287,45 @@ int register_android_view_SurfaceControl(JNIEnv* env)
gDisplayPrimariesClassInfo.white = GetFieldIDOrDie(env, displayPrimariesClazz, "white",
"Landroid/view/SurfaceControl$CieXyz;");
+ jclass RefreshRateRangeClazz =
+ FindClassOrDie(env, "android/view/SurfaceControl$RefreshRateRange");
+ gRefreshRateRangeClassInfo.clazz = MakeGlobalRefOrDie(env, RefreshRateRangeClazz);
+ gRefreshRateRangeClassInfo.ctor =
+ GetMethodIDOrDie(env, gRefreshRateRangeClassInfo.clazz, "<init>", "(FF)V");
+ gRefreshRateRangeClassInfo.min = GetFieldIDOrDie(env, RefreshRateRangeClazz, "min", "F");
+ gRefreshRateRangeClassInfo.max = GetFieldIDOrDie(env, RefreshRateRangeClazz, "max", "F");
+
+ jclass RefreshRateRangesClazz =
+ FindClassOrDie(env, "android/view/SurfaceControl$RefreshRateRanges");
+ gRefreshRateRangesClassInfo.clazz = MakeGlobalRefOrDie(env, RefreshRateRangesClazz);
+ gRefreshRateRangesClassInfo.ctor =
+ GetMethodIDOrDie(env, gRefreshRateRangesClassInfo.clazz, "<init>",
+ "(Landroid/view/SurfaceControl$RefreshRateRange;Landroid/view/"
+ "SurfaceControl$RefreshRateRange;)V");
+ gRefreshRateRangesClassInfo.physical =
+ GetFieldIDOrDie(env, RefreshRateRangesClazz, "physical",
+ "Landroid/view/SurfaceControl$RefreshRateRange;");
+ gRefreshRateRangesClassInfo.render =
+ GetFieldIDOrDie(env, RefreshRateRangesClazz, "render",
+ "Landroid/view/SurfaceControl$RefreshRateRange;");
+
jclass DesiredDisplayModeSpecsClazz =
FindClassOrDie(env, "android/view/SurfaceControl$DesiredDisplayModeSpecs");
gDesiredDisplayModeSpecsClassInfo.clazz = MakeGlobalRefOrDie(env, DesiredDisplayModeSpecsClazz);
gDesiredDisplayModeSpecsClassInfo.ctor =
- GetMethodIDOrDie(env, gDesiredDisplayModeSpecsClassInfo.clazz, "<init>", "(IZFFFF)V");
+ GetMethodIDOrDie(env, gDesiredDisplayModeSpecsClassInfo.clazz, "<init>",
+ "(IZLandroid/view/SurfaceControl$RefreshRateRanges;Landroid/view/"
+ "SurfaceControl$RefreshRateRanges;)V");
gDesiredDisplayModeSpecsClassInfo.defaultMode =
GetFieldIDOrDie(env, DesiredDisplayModeSpecsClazz, "defaultMode", "I");
gDesiredDisplayModeSpecsClassInfo.allowGroupSwitching =
GetFieldIDOrDie(env, DesiredDisplayModeSpecsClazz, "allowGroupSwitching", "Z");
- gDesiredDisplayModeSpecsClassInfo.primaryRefreshRateMin =
- GetFieldIDOrDie(env, DesiredDisplayModeSpecsClazz, "primaryRefreshRateMin", "F");
- gDesiredDisplayModeSpecsClassInfo.primaryRefreshRateMax =
- GetFieldIDOrDie(env, DesiredDisplayModeSpecsClazz, "primaryRefreshRateMax", "F");
- gDesiredDisplayModeSpecsClassInfo.appRequestRefreshRateMin =
- GetFieldIDOrDie(env, DesiredDisplayModeSpecsClazz, "appRequestRefreshRateMin", "F");
- gDesiredDisplayModeSpecsClassInfo.appRequestRefreshRateMax =
- GetFieldIDOrDie(env, DesiredDisplayModeSpecsClazz, "appRequestRefreshRateMax", "F");
+ gDesiredDisplayModeSpecsClassInfo.primaryRanges =
+ GetFieldIDOrDie(env, DesiredDisplayModeSpecsClazz, "primaryRanges",
+ "Landroid/view/SurfaceControl$RefreshRateRanges;");
+ gDesiredDisplayModeSpecsClassInfo.appRequestRanges =
+ GetFieldIDOrDie(env, DesiredDisplayModeSpecsClazz, "appRequestRanges",
+ "Landroid/view/SurfaceControl$RefreshRateRanges;");
jclass jankDataClazz =
FindClassOrDie(env, "android/view/SurfaceControl$JankData");
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 5eb15e09f09e..7e80b7d5b0ac 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -119,6 +119,7 @@ import android.view.DisplayEventReceiver;
import android.view.DisplayInfo;
import android.view.Surface;
import android.view.SurfaceControl;
+import android.view.SurfaceControl.RefreshRateRange;
import android.window.DisplayWindowPolicyController;
import android.window.ScreenCapture;
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 912b1b2e8da2..22a47393b3d6 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -33,7 +33,6 @@ import android.hardware.display.BrightnessInfo;
import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation;
-import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
import android.hardware.fingerprint.IUdfpsHbmListener;
import android.net.Uri;
import android.os.Handler;
@@ -49,6 +48,7 @@ import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.DeviceConfigInterface;
import android.provider.Settings;
+import android.sysprop.DisplayProperties;
import android.text.TextUtils;
import android.util.IndentingPrintWriter;
import android.util.Pair;
@@ -58,6 +58,8 @@ import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.view.Display;
import android.view.DisplayInfo;
+import android.view.SurfaceControl.RefreshRateRange;
+import android.view.SurfaceControl.RefreshRateRanges;
import com.android.internal.R;
import com.android.internal.annotations.GuardedBy;
@@ -135,6 +137,9 @@ public class DisplayModeDirector {
private boolean mAlwaysRespectAppRequest;
+ // TODO(b/241447632): remove the flag once SF changes are ready
+ private final boolean mRenderFrameRateIsPhysicalRefreshRate;
+
/**
* The allowed refresh rate switching type. This is used by SurfaceFlinger.
*/
@@ -170,6 +175,7 @@ public class DisplayModeDirector {
mHbmObserver = new HbmObserver(injector, ballotBox, BackgroundThread.getHandler(),
mDeviceConfigDisplaySettings);
mAlwaysRespectAppRequest = false;
+ mRenderFrameRateIsPhysicalRefreshRate = injector.renderFrameRateIsPhysicalRefreshRate();
}
/**
@@ -230,12 +236,30 @@ public class DisplayModeDirector {
}
}
}
+
+ if (mRenderFrameRateIsPhysicalRefreshRate) {
+ for (int i = 0; i < votes.size(); i++) {
+
+ Vote vote = votes.valueAt(i);
+ vote.refreshRateRanges.physical.min = Math.max(vote.refreshRateRanges.physical.min,
+ vote.refreshRateRanges.render.min);
+ vote.refreshRateRanges.physical.max = Math.min(vote.refreshRateRanges.physical.max,
+ vote.refreshRateRanges.render.max);
+ vote.refreshRateRanges.render.min = Math.max(vote.refreshRateRanges.physical.min,
+ vote.refreshRateRanges.render.min);
+ vote.refreshRateRanges.render.max = Math.min(vote.refreshRateRanges.physical.max,
+ vote.refreshRateRanges.render.max);
+ }
+ }
+
return votes;
}
private static final class VoteSummary {
- public float minRefreshRate;
- public float maxRefreshRate;
+ public float minPhysicalRefreshRate;
+ public float maxPhysicalRefreshRate;
+ public float minRenderFrameRate;
+ public float maxRenderFrameRate;
public int width;
public int height;
public boolean disableRefreshRateSwitching;
@@ -246,8 +270,10 @@ public class DisplayModeDirector {
}
public void reset() {
- minRefreshRate = 0f;
- maxRefreshRate = Float.POSITIVE_INFINITY;
+ minPhysicalRefreshRate = 0f;
+ maxPhysicalRefreshRate = Float.POSITIVE_INFINITY;
+ minRenderFrameRate = 0f;
+ maxRenderFrameRate = Float.POSITIVE_INFINITY;
width = Vote.INVALID_SIZE;
height = Vote.INVALID_SIZE;
disableRefreshRateSwitching = false;
@@ -270,9 +296,25 @@ public class DisplayModeDirector {
if (vote == null) {
continue;
}
- // For refresh rates, just use the tightest bounds of all the votes
- summary.minRefreshRate = Math.max(summary.minRefreshRate, vote.refreshRateRange.min);
- summary.maxRefreshRate = Math.min(summary.maxRefreshRate, vote.refreshRateRange.max);
+
+
+ // For physical refresh rates, just use the tightest bounds of all the votes.
+ // The refresh rate cannot be lower than the minimal render frame rate.
+ final float minPhysicalRefreshRate = Math.max(vote.refreshRateRanges.physical.min,
+ vote.refreshRateRanges.render.min);
+ summary.minPhysicalRefreshRate = Math.max(summary.minPhysicalRefreshRate,
+ minPhysicalRefreshRate);
+ summary.maxPhysicalRefreshRate = Math.min(summary.maxPhysicalRefreshRate,
+ vote.refreshRateRanges.physical.max);
+
+ // Same goes to render frame rate, but frame rate cannot exceed the max physical
+ // refresh rate
+ final float maxRenderFrameRate = Math.min(vote.refreshRateRanges.render.max,
+ vote.refreshRateRanges.physical.max);
+ summary.minRenderFrameRate = Math.max(summary.minRenderFrameRate,
+ vote.refreshRateRanges.render.min);
+ summary.maxRenderFrameRate = Math.min(summary.maxRenderFrameRate, maxRenderFrameRate);
+
// For display size, disable refresh rate switching and base mode refresh rate use only
// the first vote we come across (i.e. the highest priority vote that includes the
// attribute).
@@ -287,6 +329,20 @@ public class DisplayModeDirector {
if (summary.baseModeRefreshRate == 0f && vote.baseModeRefreshRate > 0f) {
summary.baseModeRefreshRate = vote.baseModeRefreshRate;
}
+
+ if (mLoggingEnabled) {
+ Slog.w(TAG, "Vote summary for priority "
+ + Vote.priorityToString(priority)
+ + ": width=" + summary.width
+ + ", height=" + summary.height
+ + ", minPhysicalRefreshRate=" + summary.minPhysicalRefreshRate
+ + ", maxPhysicalRefreshRate=" + summary.maxPhysicalRefreshRate
+ + ", minRenderFrameRate=" + summary.minRenderFrameRate
+ + ", maxRenderFrameRate=" + summary.maxRenderFrameRate
+ + ", disableRefreshRateSwitching="
+ + summary.disableRefreshRateSwitching
+ + ", baseModeRefreshRate=" + summary.baseModeRefreshRate);
+ }
}
}
@@ -346,8 +402,12 @@ public class DisplayModeDirector {
+ " and constraints: "
+ "width=" + primarySummary.width
+ ", height=" + primarySummary.height
- + ", minRefreshRate=" + primarySummary.minRefreshRate
- + ", maxRefreshRate=" + primarySummary.maxRefreshRate
+ + ", minPhysicalRefreshRate="
+ + primarySummary.minPhysicalRefreshRate
+ + ", maxPhysicalRefreshRate="
+ + primarySummary.maxPhysicalRefreshRate
+ + ", minRenderFrameRate=" + primarySummary.minRenderFrameRate
+ + ", maxRenderFrameRate=" + primarySummary.maxRenderFrameRate
+ ", disableRefreshRateSwitching="
+ primarySummary.disableRefreshRateSwitching
+ ", baseModeRefreshRate=" + primarySummary.baseModeRefreshRate);
@@ -361,8 +421,10 @@ public class DisplayModeDirector {
+ " and with the following constraints: "
+ "width=" + primarySummary.width
+ ", height=" + primarySummary.height
- + ", minRefreshRate=" + primarySummary.minRefreshRate
- + ", maxRefreshRate=" + primarySummary.maxRefreshRate
+ + ", minPhysicalRefreshRate=" + primarySummary.minPhysicalRefreshRate
+ + ", maxPhysicalRefreshRate=" + primarySummary.maxPhysicalRefreshRate
+ + ", minRenderFrameRate=" + primarySummary.minRenderFrameRate
+ + ", maxRenderFrameRate=" + primarySummary.maxRenderFrameRate
+ ", disableRefreshRateSwitching="
+ primarySummary.disableRefreshRateSwitching
+ ", baseModeRefreshRate=" + primarySummary.baseModeRefreshRate);
@@ -373,25 +435,53 @@ public class DisplayModeDirector {
lowestConsideredPriority++;
}
+ if (mLoggingEnabled) {
+ Slog.i(TAG,
+ "Primary physical range: ["
+ + primarySummary.minPhysicalRefreshRate
+ + " "
+ + primarySummary.maxPhysicalRefreshRate
+ + "] render frame rate range: ["
+ + primarySummary.minRenderFrameRate
+ + " "
+ + primarySummary.maxRenderFrameRate
+ + "]");
+ }
+
VoteSummary appRequestSummary = new VoteSummary();
summarizeVotes(
votes,
Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF,
Vote.MAX_PRIORITY,
appRequestSummary);
- appRequestSummary.minRefreshRate =
- Math.min(appRequestSummary.minRefreshRate, primarySummary.minRefreshRate);
- appRequestSummary.maxRefreshRate =
- Math.max(appRequestSummary.maxRefreshRate, primarySummary.maxRefreshRate);
+ appRequestSummary.minPhysicalRefreshRate =
+ Math.min(appRequestSummary.minPhysicalRefreshRate,
+ primarySummary.minPhysicalRefreshRate);
+ appRequestSummary.maxPhysicalRefreshRate =
+ Math.max(appRequestSummary.maxPhysicalRefreshRate,
+ primarySummary.maxPhysicalRefreshRate);
+ appRequestSummary.minRenderFrameRate =
+ Math.min(appRequestSummary.minRenderFrameRate,
+ primarySummary.minRenderFrameRate);
+ appRequestSummary.maxRenderFrameRate =
+ Math.max(appRequestSummary.maxRenderFrameRate,
+ primarySummary.maxRenderFrameRate);
if (mLoggingEnabled) {
Slog.i(TAG,
- String.format("App request range: [%.0f %.0f]",
- appRequestSummary.minRefreshRate,
- appRequestSummary.maxRefreshRate));
- }
-
- // Select the base mode id based on the base mode refresh rate, if available, since this
- // will be the mode id the app voted for.
+ "App request range: ["
+ + appRequestSummary.minPhysicalRefreshRate
+ + " "
+ + appRequestSummary.maxPhysicalRefreshRate
+ + "] Frame rate range: ["
+ + appRequestSummary.minRenderFrameRate
+ + " "
+ + appRequestSummary.maxRenderFrameRate
+ + "]");
+ }
+
+ // Select the base mode id based on the base mode physical refresh rate,
+ // if available, since this will be the mode id the
+ // app voted for.
Display.Mode baseMode = null;
for (Display.Mode availableMode : availableModes) {
if (primarySummary.baseModeRefreshRate
@@ -427,18 +517,26 @@ public class DisplayModeDirector {
+ ", supported modes = " + Arrays.toString(modes));
float fps = defaultMode.getRefreshRate();
+ final RefreshRateRange range = new RefreshRateRange(fps, fps);
+ final RefreshRateRanges ranges = new RefreshRateRanges(range, range);
return new DesiredDisplayModeSpecs(defaultMode.getModeId(),
/*allowGroupSwitching */ false,
- new RefreshRateRange(fps, fps),
- new RefreshRateRange(fps, fps));
+ ranges, ranges);
}
if (mModeSwitchingType == DisplayManager.SWITCHING_TYPE_NONE
|| primarySummary.disableRefreshRateSwitching) {
float fps = baseMode.getRefreshRate();
- primarySummary.minRefreshRate = primarySummary.maxRefreshRate = fps;
+ primarySummary.minPhysicalRefreshRate = primarySummary.maxPhysicalRefreshRate = fps;
+ if (mRenderFrameRateIsPhysicalRefreshRate) {
+ primarySummary.minRenderFrameRate = primarySummary.maxRenderFrameRate = fps;
+ }
if (mModeSwitchingType == DisplayManager.SWITCHING_TYPE_NONE) {
- appRequestSummary.minRefreshRate = appRequestSummary.maxRefreshRate = fps;
+ primarySummary.minRenderFrameRate = primarySummary.maxRenderFrameRate = fps;
+ appRequestSummary.minPhysicalRefreshRate =
+ appRequestSummary.maxPhysicalRefreshRate = fps;
+ appRequestSummary.minRenderFrameRate =
+ appRequestSummary.maxRenderFrameRate = fps;
}
}
@@ -447,15 +545,34 @@ public class DisplayModeDirector {
return new DesiredDisplayModeSpecs(baseMode.getModeId(),
allowGroupSwitching,
- new RefreshRateRange(
- primarySummary.minRefreshRate, primarySummary.maxRefreshRate),
- new RefreshRateRange(
- appRequestSummary.minRefreshRate, appRequestSummary.maxRefreshRate));
+ new RefreshRateRanges(
+ new RefreshRateRange(
+ primarySummary.minPhysicalRefreshRate,
+ primarySummary.maxPhysicalRefreshRate),
+ new RefreshRateRange(
+ primarySummary.minRenderFrameRate,
+ primarySummary.maxRenderFrameRate)),
+ new RefreshRateRanges(
+ new RefreshRateRange(
+ appRequestSummary.minPhysicalRefreshRate,
+ appRequestSummary.maxPhysicalRefreshRate),
+ new RefreshRateRange(
+ appRequestSummary.minRenderFrameRate,
+ appRequestSummary.maxRenderFrameRate)));
}
}
private ArrayList<Display.Mode> filterModes(Display.Mode[] supportedModes,
VoteSummary summary) {
+ if (summary.minRenderFrameRate > summary.maxRenderFrameRate + FLOAT_TOLERANCE) {
+ if (mLoggingEnabled) {
+ Slog.w(TAG, "Vote summary resulted in empty set (invalid frame rate range)"
+ + ": minRenderFrameRate=" + summary.minRenderFrameRate
+ + ", maxRenderFrameRate=" + summary.maxRenderFrameRate);
+ }
+ return new ArrayList<>();
+ }
+
ArrayList<Display.Mode> availableModes = new ArrayList<>();
boolean missingBaseModeRefreshRate = summary.baseModeRefreshRate > 0f;
for (Display.Mode mode : supportedModes) {
@@ -470,21 +587,44 @@ public class DisplayModeDirector {
}
continue;
}
- final float refreshRate = mode.getRefreshRate();
+ final float physicalRefreshRate = mode.getRefreshRate();
// Some refresh rates are calculated based on frame timings, so they aren't *exactly*
// equal to expected refresh rate. Given that, we apply a bit of tolerance to this
// comparison.
- if (refreshRate < (summary.minRefreshRate - FLOAT_TOLERANCE)
- || refreshRate > (summary.maxRefreshRate + FLOAT_TOLERANCE)) {
+ if (physicalRefreshRate < (summary.minPhysicalRefreshRate - FLOAT_TOLERANCE)
+ || physicalRefreshRate > (summary.maxPhysicalRefreshRate + FLOAT_TOLERANCE)) {
if (mLoggingEnabled) {
Slog.w(TAG, "Discarding mode " + mode.getModeId()
+ ", outside refresh rate bounds"
- + ": minRefreshRate=" + summary.minRefreshRate
- + ", maxRefreshRate=" + summary.maxRefreshRate
- + ", modeRefreshRate=" + refreshRate);
+ + ": minPhysicalRefreshRate=" + summary.minPhysicalRefreshRate
+ + ", maxPhysicalRefreshRate=" + summary.maxPhysicalRefreshRate
+ + ", modeRefreshRate=" + physicalRefreshRate);
+ }
+ continue;
+ }
+
+ // Check whether the render frame rate range is achievable by the mode's physical
+ // refresh rate, meaning that if a divisor of the physical refresh rate is in range
+ // of the render frame rate.
+ // For example for the render frame rate [50, 70]:
+ // - 120Hz is in range as we can render at 60hz by skipping every other frame,
+ // which is within the render rate range
+ // - 90hz is not in range as none of the even divisors (i.e. 90, 45, 30)
+ // fall within the acceptable render range.
+ final int divisor = (int) Math.ceil(physicalRefreshRate / summary.maxRenderFrameRate);
+ float adjustedPhysicalRefreshRate = physicalRefreshRate / divisor;
+ if (adjustedPhysicalRefreshRate < (summary.minRenderFrameRate - FLOAT_TOLERANCE)) {
+ if (mLoggingEnabled) {
+ Slog.w(TAG, "Discarding mode " + mode.getModeId()
+ + " with adjusted refresh rate: " + adjustedPhysicalRefreshRate
+ + ", outside frame rate bounds"
+ + ": minRenderFrameRate=" + summary.minRenderFrameRate
+ + ", maxRenderFrameRate=" + summary.maxRenderFrameRate
+ + ", modePhysicalRefreshRate=" + physicalRefreshRate);
}
continue;
}
+
availableModes.add(mode);
if (mode.getRefreshRate() >= summary.baseModeRefreshRate - FLOAT_TOLERANCE
&& mode.getRefreshRate() <= summary.baseModeRefreshRate + FLOAT_TOLERANCE) {
@@ -854,30 +994,30 @@ public class DisplayModeDirector {
public boolean allowGroupSwitching;
/**
- * The primary refresh rate range.
+ * The primary refresh rate ranges.
*/
- public final RefreshRateRange primaryRefreshRateRange;
+ public final RefreshRateRanges primary;
/**
- * The app request refresh rate range. Lower priority considerations won't be included in
+ * The app request refresh rate ranges. Lower priority considerations won't be included in
* this range, allowing SurfaceFlinger to consider additional refresh rates for apps that
* call setFrameRate(). This range will be greater than or equal to the primary refresh rate
* range, never smaller.
*/
- public final RefreshRateRange appRequestRefreshRateRange;
+ public final RefreshRateRanges appRequest;
public DesiredDisplayModeSpecs() {
- primaryRefreshRateRange = new RefreshRateRange();
- appRequestRefreshRateRange = new RefreshRateRange();
+ primary = new RefreshRateRanges();
+ appRequest = new RefreshRateRanges();
}
public DesiredDisplayModeSpecs(int baseModeId,
boolean allowGroupSwitching,
- @NonNull RefreshRateRange primaryRefreshRateRange,
- @NonNull RefreshRateRange appRequestRefreshRateRange) {
+ @NonNull RefreshRateRanges primary,
+ @NonNull RefreshRateRanges appRequest) {
this.baseModeId = baseModeId;
this.allowGroupSwitching = allowGroupSwitching;
- this.primaryRefreshRateRange = primaryRefreshRateRange;
- this.appRequestRefreshRateRange = appRequestRefreshRateRange;
+ this.primary = primary;
+ this.appRequest = appRequest;
}
/**
@@ -886,12 +1026,12 @@ public class DisplayModeDirector {
@Override
public String toString() {
return String.format("baseModeId=%d allowGroupSwitching=%b"
- + " primaryRefreshRateRange=[%.0f %.0f]"
- + " appRequestRefreshRateRange=[%.0f %.0f]",
- baseModeId, allowGroupSwitching, primaryRefreshRateRange.min,
- primaryRefreshRateRange.max, appRequestRefreshRateRange.min,
- appRequestRefreshRateRange.max);
+ + " primary=%s"
+ + " appRequest=%s",
+ baseModeId, allowGroupSwitching, primary.toString(),
+ appRequest.toString());
}
+
/**
* Checks whether the two objects have the same values.
*/
@@ -913,11 +1053,11 @@ public class DisplayModeDirector {
if (allowGroupSwitching != desiredDisplayModeSpecs.allowGroupSwitching) {
return false;
}
- if (!primaryRefreshRateRange.equals(desiredDisplayModeSpecs.primaryRefreshRateRange)) {
+ if (!primary.equals(desiredDisplayModeSpecs.primary)) {
return false;
}
- if (!appRequestRefreshRateRange.equals(
- desiredDisplayModeSpecs.appRequestRefreshRateRange)) {
+ if (!appRequest.equals(
+ desiredDisplayModeSpecs.appRequest)) {
return false;
}
return true;
@@ -925,8 +1065,7 @@ public class DisplayModeDirector {
@Override
public int hashCode() {
- return Objects.hash(baseModeId, allowGroupSwitching, primaryRefreshRateRange,
- appRequestRefreshRateRange);
+ return Objects.hash(baseModeId, allowGroupSwitching, primary, appRequest);
}
/**
@@ -935,18 +1074,24 @@ public class DisplayModeDirector {
public void copyFrom(DesiredDisplayModeSpecs other) {
baseModeId = other.baseModeId;
allowGroupSwitching = other.allowGroupSwitching;
- primaryRefreshRateRange.min = other.primaryRefreshRateRange.min;
- primaryRefreshRateRange.max = other.primaryRefreshRateRange.max;
- appRequestRefreshRateRange.min = other.appRequestRefreshRateRange.min;
- appRequestRefreshRateRange.max = other.appRequestRefreshRateRange.max;
+ primary.physical.min = other.primary.physical.min;
+ primary.physical.max = other.primary.physical.max;
+ primary.render.min = other.primary.render.min;
+ primary.render.max = other.primary.render.max;
+
+ appRequest.physical.min = other.appRequest.physical.min;
+ appRequest.physical.max = other.appRequest.physical.max;
+ appRequest.render.min = other.appRequest.render.min;
+ appRequest.render.max = other.appRequest.render.max;
}
}
@VisibleForTesting
static final class Vote {
- // DEFAULT_FRAME_RATE votes for [0, DEFAULT]. As the lowest priority vote, it's overridden
- // by all other considerations. It acts to set a default frame rate for a device.
- public static final int PRIORITY_DEFAULT_REFRESH_RATE = 0;
+ // DEFAULT_RENDER_FRAME_RATE votes for render frame rate [0, DEFAULT]. As the lowest
+ // priority vote, it's overridden by all other considerations. It acts to set a default
+ // frame rate for a device.
+ public static final int PRIORITY_DEFAULT_RENDER_FRAME_RATE = 0;
// PRIORITY_FLICKER_REFRESH_RATE votes for a single refresh rate like [60,60], [90,90] or
// null. It is used to set a preferred refresh rate value in case the higher priority votes
@@ -956,16 +1101,16 @@ public class DisplayModeDirector {
// High-brightness-mode may need a specific range of refresh-rates to function properly.
public static final int PRIORITY_HIGH_BRIGHTNESS_MODE = 2;
- // SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate.
+ // SETTING_MIN_RENDER_FRAME_RATE is used to propose a lower bound of the render frame rate.
// It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
- public static final int PRIORITY_USER_SETTING_MIN_REFRESH_RATE = 3;
+ public static final int PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE = 3;
- // APP_REQUEST_REFRESH_RATE_RANGE is used to for internal apps to limit the refresh
- // rate in certain cases, mostly to preserve power.
+ // APP_REQUEST_RENDER_FRAME_RATE_RANGE is used to for internal apps to limit the render
+ // frame rate in certain cases, mostly to preserve power.
// @see android.view.WindowManager.LayoutParams#preferredMinRefreshRate
// @see android.view.WindowManager.LayoutParams#preferredMaxRefreshRate
// It votes to [preferredMinRefreshRate, preferredMaxRefreshRate].
- public static final int PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE = 4;
+ public static final int PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE = 4;
// We split the app request into different priorities in case we can satisfy one desire
// without the other.
@@ -983,11 +1128,12 @@ public class DisplayModeDirector {
public static final int PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE = 5;
public static final int PRIORITY_APP_REQUEST_SIZE = 6;
- // 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 = 7;
+ // SETTING_PEAK_RENDER_FRAME_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_RENDER_FRAME_RATE = 7;
- // LOW_POWER_MODE force display to [0, 60HZ] if Settings.Global.LOW_POWER_MODE is on.
+ // LOW_POWER_MODE force the render frame rate to [0, 60HZ] if
+ // Settings.Global.LOW_POWER_MODE is on.
public static final int PRIORITY_LOW_POWER_MODE = 8;
// PRIORITY_FLICKER_REFRESH_RATE_SWITCH votes for disabling refresh rate switching. If the
@@ -1010,13 +1156,13 @@ public class DisplayModeDirector {
// Whenever a new priority is added, remember to update MIN_PRIORITY, MAX_PRIORITY, and
// APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, as well as priorityToString.
- public static final int MIN_PRIORITY = PRIORITY_DEFAULT_REFRESH_RATE;
+ public static final int MIN_PRIORITY = PRIORITY_DEFAULT_RENDER_FRAME_RATE;
public static final int MAX_PRIORITY = PRIORITY_UDFPS;
// The cutoff for the app request refresh rate range. Votes with priorities lower than this
// value will not be considered when constructing the app request refresh rate range.
public static final int APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF =
- PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE;
+ PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE;
/**
* A value signifying an invalid width or height in a vote.
@@ -1032,9 +1178,9 @@ public class DisplayModeDirector {
*/
public final int height;
/**
- * Information about the min and max refresh rate DM would like to set the display to.
+ * Information about the refresh rate frame rate ranges DM would like to set the display to.
*/
- public final RefreshRateRange refreshRateRange;
+ public final RefreshRateRanges refreshRateRanges;
/**
* Whether refresh rate switching should be disabled (i.e. the refresh rate range is
@@ -1048,34 +1194,48 @@ public class DisplayModeDirector {
*/
public final float baseModeRefreshRate;
- public static Vote forRefreshRates(float minRefreshRate, float maxRefreshRate) {
- return new Vote(INVALID_SIZE, INVALID_SIZE, minRefreshRate, maxRefreshRate,
+ public static Vote forPhysicalRefreshRates(float minRefreshRate, float maxRefreshRate) {
+ return new Vote(INVALID_SIZE, INVALID_SIZE, minRefreshRate, maxRefreshRate, 0,
+ Float.POSITIVE_INFINITY,
minRefreshRate == maxRefreshRate, 0f);
}
+ public static Vote forRenderFrameRates(float minFrameRate, float maxFrameRate) {
+ return new Vote(INVALID_SIZE, INVALID_SIZE, 0, Float.POSITIVE_INFINITY, minFrameRate,
+ maxFrameRate,
+ false, 0f);
+ }
+
public static Vote forSize(int width, int height) {
- return new Vote(width, height, 0f, Float.POSITIVE_INFINITY, false,
+ return new Vote(width, height, 0, Float.POSITIVE_INFINITY, 0, Float.POSITIVE_INFINITY,
+ false,
0f);
}
public static Vote forDisableRefreshRateSwitching() {
- return new Vote(INVALID_SIZE, INVALID_SIZE, 0f, Float.POSITIVE_INFINITY, true,
+ return new Vote(INVALID_SIZE, INVALID_SIZE, 0, Float.POSITIVE_INFINITY, 0,
+ Float.POSITIVE_INFINITY, true,
0f);
}
public static Vote forBaseModeRefreshRate(float baseModeRefreshRate) {
- return new Vote(INVALID_SIZE, INVALID_SIZE, 0f, Float.POSITIVE_INFINITY, false,
+ return new Vote(INVALID_SIZE, INVALID_SIZE, 0, Float.POSITIVE_INFINITY, 0,
+ Float.POSITIVE_INFINITY, false,
baseModeRefreshRate);
}
private Vote(int width, int height,
- float minRefreshRate, float maxRefreshRate,
+ float minPhysicalRefreshRate,
+ float maxPhysicalRefreshRate,
+ float minRenderFrameRate,
+ float maxRenderFrameRate,
boolean disableRefreshRateSwitching,
float baseModeRefreshRate) {
this.width = width;
this.height = height;
- this.refreshRateRange =
- new RefreshRateRange(minRefreshRate, maxRefreshRate);
+ this.refreshRateRanges = new RefreshRateRanges(
+ new RefreshRateRange(minPhysicalRefreshRate, maxPhysicalRefreshRate),
+ new RefreshRateRange(minRenderFrameRate, maxRenderFrameRate));
this.disableRefreshRateSwitching = disableRefreshRateSwitching;
this.baseModeRefreshRate = baseModeRefreshRate;
}
@@ -1084,11 +1244,11 @@ public class DisplayModeDirector {
switch (priority) {
case PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE:
return "PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE";
- case PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE:
- return "PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE";
+ case PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE:
+ return "PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE";
case PRIORITY_APP_REQUEST_SIZE:
return "PRIORITY_APP_REQUEST_SIZE";
- case PRIORITY_DEFAULT_REFRESH_RATE:
+ case PRIORITY_DEFAULT_RENDER_FRAME_RATE:
return "PRIORITY_DEFAULT_REFRESH_RATE";
case PRIORITY_FLICKER_REFRESH_RATE:
return "PRIORITY_FLICKER_REFRESH_RATE";
@@ -1104,10 +1264,10 @@ public class DisplayModeDirector {
return "PRIORITY_SKIN_TEMPERATURE";
case PRIORITY_UDFPS:
return "PRIORITY_UDFPS";
- case PRIORITY_USER_SETTING_MIN_REFRESH_RATE:
- return "PRIORITY_USER_SETTING_MIN_REFRESH_RATE";
- case PRIORITY_USER_SETTING_PEAK_REFRESH_RATE:
- return "PRIORITY_USER_SETTING_PEAK_REFRESH_RATE";
+ case PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE:
+ return "PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE";
+ case PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE:
+ return "PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE";
default:
return Integer.toString(priority);
}
@@ -1116,11 +1276,10 @@ public class DisplayModeDirector {
@Override
public String toString() {
return "Vote{"
- + "width=" + width + ", height=" + height
- + ", minRefreshRate=" + refreshRateRange.min
- + ", maxRefreshRate=" + refreshRateRange.max
- + ", disableRefreshRateSwitching=" + disableRefreshRateSwitching
- + ", baseModeRefreshRate=" + baseModeRefreshRate + "}";
+ + "width=" + width + ", height=" + height
+ + ", refreshRateRanges=" + refreshRateRanges
+ + ", disableRefreshRateSwitching=" + disableRefreshRateSwitching
+ + ", baseModeRefreshRate=" + baseModeRefreshRate + "}";
}
}
@@ -1237,7 +1396,7 @@ public class DisplayModeDirector {
Settings.Global.LOW_POWER_MODE, 0 /*default*/) != 0;
final Vote vote;
if (inLowPowerMode) {
- vote = Vote.forRefreshRates(0f, 60f);
+ vote = Vote.forRenderFrameRates(0f, 60f);
} else {
vote = null;
}
@@ -1262,13 +1421,14 @@ public class DisplayModeDirector {
// than necessary, and we should improve it. See b/156304339 for more info.
Vote peakVote = peakRefreshRate == 0f
? null
- : Vote.forRefreshRates(0f, Math.max(minRefreshRate, peakRefreshRate));
- updateVoteLocked(Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE, peakVote);
- updateVoteLocked(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE,
- Vote.forRefreshRates(minRefreshRate, Float.POSITIVE_INFINITY));
+ : Vote.forRenderFrameRates(0f, Math.max(minRefreshRate, peakRefreshRate));
+ updateVoteLocked(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE, peakVote);
+ updateVoteLocked(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(minRefreshRate, Float.POSITIVE_INFINITY));
Vote defaultVote =
- defaultRefreshRate == 0f ? null : Vote.forRefreshRates(0f, defaultRefreshRate);
- updateVoteLocked(Vote.PRIORITY_DEFAULT_REFRESH_RATE, defaultVote);
+ defaultRefreshRate == 0f
+ ? null : Vote.forRenderFrameRates(0f, defaultRefreshRate);
+ updateVoteLocked(Vote.PRIORITY_DEFAULT_RENDER_FRAME_RATE, defaultVote);
float maxRefreshRate;
if (peakRefreshRate == 0f && defaultRefreshRate == 0f) {
@@ -1374,13 +1534,15 @@ public class DisplayModeDirector {
if (refreshRateRange != null) {
mAppPreferredRefreshRateRangeByDisplay.put(displayId, refreshRateRange);
- vote = Vote.forRefreshRates(refreshRateRange.min, refreshRateRange.max);
+ vote = Vote.forRenderFrameRates(refreshRateRange.min, refreshRateRange.max);
} else {
mAppPreferredRefreshRateRangeByDisplay.remove(displayId);
vote = null;
}
synchronized (mLock) {
- updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE, vote);
+ updateVoteLocked(displayId,
+ Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE,
+ vote);
}
}
@@ -1956,6 +2118,7 @@ public class DisplayModeDirector {
return false;
}
+
private void onBrightnessChangedLocked() {
Vote refreshRateVote = null;
Vote refreshRateSwitchingVote = null;
@@ -1969,7 +2132,7 @@ public class DisplayModeDirector {
boolean insideLowZone = hasValidLowZone() && isInsideLowZone(mBrightness, mAmbientLux);
if (insideLowZone) {
refreshRateVote =
- Vote.forRefreshRates(mRefreshRateInLowZone, mRefreshRateInLowZone);
+ Vote.forPhysicalRefreshRates(mRefreshRateInLowZone, mRefreshRateInLowZone);
refreshRateSwitchingVote = Vote.forDisableRefreshRateSwitching();
}
@@ -1977,7 +2140,8 @@ public class DisplayModeDirector {
&& isInsideHighZone(mBrightness, mAmbientLux);
if (insideHighZone) {
refreshRateVote =
- Vote.forRefreshRates(mRefreshRateInHighZone, mRefreshRateInHighZone);
+ Vote.forPhysicalRefreshRates(mRefreshRateInHighZone,
+ mRefreshRateInHighZone);
refreshRateSwitchingVote = Vote.forDisableRefreshRateSwitching();
}
@@ -2222,7 +2386,7 @@ public class DisplayModeDirector {
maxRefreshRate = mode.getRefreshRate();
}
}
- vote = Vote.forRefreshRates(maxRefreshRate, maxRefreshRate);
+ vote = Vote.forPhysicalRefreshRates(maxRefreshRate, maxRefreshRate);
} else {
vote = null;
}
@@ -2303,7 +2467,7 @@ public class DisplayModeDirector {
mDisplayManagerInternal.getRefreshRateForDisplayAndSensor(
displayId, mProximitySensorName, mProximitySensorType);
if (rate != null) {
- vote = Vote.forRefreshRates(rate.min, rate.max);
+ vote = Vote.forPhysicalRefreshRates(rate.min, rate.max);
}
}
mBallotBox.vote(displayId, Vote.PRIORITY_PROXIMITY, vote);
@@ -2472,7 +2636,7 @@ public class DisplayModeDirector {
if (hbmMode == BrightnessInfo.HIGH_BRIGHTNESS_MODE_SUNLIGHT) {
// Device resource properties take priority over DisplayDeviceConfig
if (mRefreshRateInHbmSunlight > 0) {
- vote = Vote.forRefreshRates(mRefreshRateInHbmSunlight,
+ vote = Vote.forPhysicalRefreshRates(mRefreshRateInHbmSunlight,
mRefreshRateInHbmSunlight);
} else {
final List<RefreshRateLimitation> limits =
@@ -2480,7 +2644,7 @@ public class DisplayModeDirector {
for (int i = 0; limits != null && i < limits.size(); i++) {
final RefreshRateLimitation limitation = limits.get(i);
if (limitation.type == REFRESH_RATE_LIMIT_HIGH_BRIGHTNESS_MODE) {
- vote = Vote.forRefreshRates(limitation.range.min,
+ vote = Vote.forPhysicalRefreshRates(limitation.range.min,
limitation.range.max);
break;
}
@@ -2490,7 +2654,7 @@ public class DisplayModeDirector {
mRefreshRateInHbmHdr > 0) {
// HBM for HDR vote isn't supported through DisplayDeviceConfig yet, so look for
// a vote from Device properties
- vote = Vote.forRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr);
+ vote = Vote.forPhysicalRefreshRates(mRefreshRateInHbmHdr, mRefreshRateInHbmHdr);
} else {
Slog.w(TAG, "Unexpected HBM mode " + hbmMode + " for display ID " + displayId);
}
@@ -2528,7 +2692,7 @@ public class DisplayModeDirector {
}
final Vote vote;
if (mStatus >= Temperature.THROTTLING_CRITICAL) {
- vote = Vote.forRefreshRates(0f, 60f);
+ vote = Vote.forRenderFrameRates(0f, 60f);
} else {
vote = null;
}
@@ -2741,6 +2905,8 @@ public class DisplayModeDirector {
boolean isDozeState(Display d);
IThermalService getThermalService();
+
+ boolean renderFrameRateIsPhysicalRefreshRate();
}
@VisibleForTesting
@@ -2794,6 +2960,12 @@ public class DisplayModeDirector {
ServiceManager.getService(Context.THERMAL_SERVICE));
}
+ @Override
+ public boolean renderFrameRateIsPhysicalRefreshRate() {
+ return DisplayProperties
+ .debug_render_frame_rate_is_physical_refresh_rate().orElse(true);
+ }
+
private DisplayManager getDisplayManager() {
if (mDisplayManager == null) {
mDisplayManager = mContext.getSystemService(DisplayManager.class);
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 002209e32304..2c2075d33bb9 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -387,14 +387,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
// list of available modes will take care of updating display mode specs.
if (activeBaseMode == INVALID_MODE_ID
|| mDisplayModeSpecs.baseModeId != activeBaseMode
- || mDisplayModeSpecs.primaryRefreshRateRange.min
- != modeSpecs.primaryRefreshRateMin
- || mDisplayModeSpecs.primaryRefreshRateRange.max
- != modeSpecs.primaryRefreshRateMax
- || mDisplayModeSpecs.appRequestRefreshRateRange.min
- != modeSpecs.appRequestRefreshRateMin
- || mDisplayModeSpecs.appRequestRefreshRateRange.max
- != modeSpecs.appRequestRefreshRateMax) {
+ || !mDisplayModeSpecs.primary.equals(modeSpecs.primaryRanges)
+ || !mDisplayModeSpecs.appRequest.equals(modeSpecs.appRequestRanges)) {
mDisplayModeSpecsInvalid = true;
sendTraversalRequestLocked();
}
@@ -997,10 +991,8 @@ final class LocalDisplayAdapter extends DisplayAdapter {
getDisplayTokenLocked(),
new SurfaceControl.DesiredDisplayModeSpecs(baseSfModeId,
mDisplayModeSpecs.allowGroupSwitching,
- mDisplayModeSpecs.primaryRefreshRateRange.min,
- mDisplayModeSpecs.primaryRefreshRateRange.max,
- mDisplayModeSpecs.appRequestRefreshRateRange.min,
- mDisplayModeSpecs.appRequestRefreshRateRange.max)));
+ mDisplayModeSpecs.primary,
+ mDisplayModeSpecs.appRequest)));
}
}
diff --git a/services/core/java/com/android/server/wm/RefreshRatePolicy.java b/services/core/java/com/android/server/wm/RefreshRatePolicy.java
index f3713eb7f474..ccc71bb8c537 100644
--- a/services/core/java/com/android/server/wm/RefreshRatePolicy.java
+++ b/services/core/java/com/android/server/wm/RefreshRatePolicy.java
@@ -19,10 +19,10 @@ package com.android.server.wm;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
-import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
import android.view.Display;
import android.view.Display.Mode;
import android.view.DisplayInfo;
+import android.view.SurfaceControl.RefreshRateRange;
import java.util.HashMap;
diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
index 3866da33a24e..d41ac7021077 100644
--- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java
@@ -35,7 +35,6 @@ import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
-import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
@@ -43,6 +42,8 @@ import android.os.Looper;
import android.view.Display;
import android.view.DisplayAddress;
import android.view.SurfaceControl;
+import android.view.SurfaceControl.RefreshRateRange;
+import android.view.SurfaceControl.RefreshRateRanges;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
@@ -75,6 +76,11 @@ public class LocalDisplayAdapterTest {
private static final int PORT_A = 0;
private static final int PORT_B = 0x80;
private static final int PORT_C = 0xFF;
+ private static final float REFRESH_RATE = 60f;
+ private static final RefreshRateRange REFRESH_RATE_RANGE =
+ new RefreshRateRange(REFRESH_RATE, REFRESH_RATE);
+ private static final RefreshRateRanges REFRESH_RATE_RANGES =
+ new RefreshRateRanges(REFRESH_RATE_RANGE, REFRESH_RATE_RANGE);
private static final long HANDLER_WAIT_MS = 100;
@@ -697,16 +703,14 @@ public class LocalDisplayAdapterTest {
new DisplayModeDirector.DesiredDisplayModeSpecs(
/*baseModeId*/ baseModeId,
/*allowGroupSwitching*/ false,
- new RefreshRateRange(60f, 60f),
- new RefreshRateRange(60f, 60f)
+ REFRESH_RATE_RANGES, REFRESH_RATE_RANGES
));
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
verify(mSurfaceControlProxy).setDesiredDisplayModeSpecs(display.token,
new SurfaceControl.DesiredDisplayModeSpecs(
/* baseModeId */ 0,
/* allowGroupSwitching */ false,
- /* primaryRange */ 60f, 60f,
- /* appRange */ 60f, 60f
+ REFRESH_RATE_RANGES, REFRESH_RATE_RANGES
));
// Change the display
@@ -732,8 +736,7 @@ public class LocalDisplayAdapterTest {
new DisplayModeDirector.DesiredDisplayModeSpecs(
/*baseModeId*/ baseModeId,
/*allowGroupSwitching*/ false,
- new RefreshRateRange(60f, 60f),
- new RefreshRateRange(60f, 60f)
+ REFRESH_RATE_RANGES, REFRESH_RATE_RANGES
));
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
@@ -743,8 +746,7 @@ public class LocalDisplayAdapterTest {
new SurfaceControl.DesiredDisplayModeSpecs(
/* baseModeId */ 2,
/* allowGroupSwitching */ false,
- /* primaryRange */ 60f, 60f,
- /* appRange */ 60f, 60f
+ REFRESH_RATE_RANGES, REFRESH_RATE_RANGES
));
}
@@ -922,12 +924,11 @@ public class LocalDisplayAdapterTest {
}
public SurfaceControl.DesiredDisplayModeSpecs desiredDisplayModeSpecs =
- new SurfaceControl.DesiredDisplayModeSpecs(/* defaultMode */ 0,
- /* allowGroupSwitching */ false,
- /* primaryRefreshRateMin */ 60.f,
- /* primaryRefreshRateMax */ 60.f,
- /* appRefreshRateMin */ 60.f,
- /* appRefreshRateMax */60.f);
+ new SurfaceControl.DesiredDisplayModeSpecs(
+ /* defaultMode */ 0,
+ /* allowGroupSwitching */ false,
+ REFRESH_RATE_RANGES, REFRESH_RATE_RANGES
+ );
private FakeDisplay(int port) {
address = createDisplayAddress(port);
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index 18dd264558ac..f8dd4436fac0 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -57,7 +57,6 @@ import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManager.DisplayListener;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.RefreshRateLimitation;
-import android.hardware.display.DisplayManagerInternal.RefreshRateRange;
import android.hardware.fingerprint.IUdfpsHbmListener;
import android.os.Handler;
import android.os.IThermalEventListener;
@@ -71,10 +70,11 @@ import android.test.mock.MockContentResolver;
import android.util.Slog;
import android.util.SparseArray;
import android.view.Display;
+import android.view.SurfaceControl.RefreshRateRange;
+import android.view.SurfaceControl.RefreshRateRanges;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.SmallTest;
-import androidx.test.runner.AndroidJUnit4;
import com.android.internal.display.BrightnessSynchronizer;
import com.android.internal.util.Preconditions;
@@ -105,8 +105,11 @@ import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
+import junitparams.JUnitParamsRunner;
+import junitparams.Parameters;
+
@SmallTest
-@RunWith(AndroidJUnit4.class)
+@RunWith(JUnitParamsRunner.class)
public class DisplayModeDirectorTest {
// The tolerance within which we consider something approximately equals.
private static final String TAG = "DisplayModeDirectorTest";
@@ -154,8 +157,6 @@ public class DisplayModeDirectorTest {
private DisplayModeDirector createDirectorFromRefreshRateArray(
float[] refreshRates, int baseModeId, float defaultRefreshRate) {
- DisplayModeDirector director =
- new DisplayModeDirector(mContext, mHandler, mInjector);
Display.Mode[] modes = new Display.Mode[refreshRates.length];
Display.Mode defaultMode = null;
for (int i = 0; i < refreshRates.length; i++) {
@@ -194,13 +195,24 @@ public class DisplayModeDirectorTest {
}
@Test
- public void testDisplayModeVoting() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testDisplayModeVoting(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
// With no votes present, DisplayModeDirector should allow any refresh rate.
- DesiredDisplayModeSpecs modeSpecs =
- createDirectorFromFpsRange(60, 90).getDesiredDisplayModeSpecs(DISPLAY_ID);
+ DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
+ DesiredDisplayModeSpecs modeSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(modeSpecs.baseModeId).isEqualTo(60);
- assertThat(modeSpecs.primaryRefreshRateRange.min).isEqualTo(0f);
- assertThat(modeSpecs.primaryRefreshRateRange.max).isEqualTo(Float.POSITIVE_INFINITY);
+ assertThat(modeSpecs.primary.physical.min).isEqualTo(0f);
+ assertThat(modeSpecs.primary.physical.max).isEqualTo(Float.POSITIVE_INFINITY);
+ assertThat(modeSpecs.primary.render.min).isEqualTo(0f);
+ assertThat(modeSpecs.primary.render.max).isEqualTo(Float.POSITIVE_INFINITY);
+ assertThat(modeSpecs.appRequest.physical.min).isEqualTo(0f);
+ assertThat(modeSpecs.appRequest.physical.max).isEqualTo(Float.POSITIVE_INFINITY);
+ assertThat(modeSpecs.appRequest.render.min).isEqualTo(0f);
+ assertThat(modeSpecs.appRequest.render.max).isEqualTo(Float.POSITIVE_INFINITY);
int numPriorities =
DisplayModeDirector.Vote.MAX_PRIORITY - DisplayModeDirector.Vote.MIN_PRIORITY + 1;
@@ -210,21 +222,49 @@ public class DisplayModeDirectorTest {
{
int minFps = 60;
int maxFps = 90;
- DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
+ director = createDirectorFromFpsRange(60, 90);
assertTrue(2 * numPriorities < maxFps - minFps + 1);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
for (int i = 0; i < numPriorities; i++) {
int priority = Vote.MIN_PRIORITY + i;
- votes.put(priority, Vote.forRefreshRates(minFps + i, maxFps - i));
+ votes.put(priority, Vote.forPhysicalRefreshRates(minFps + i, maxFps - i));
director.injectVotesByDisplay(votesByDisplay);
modeSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(modeSpecs.baseModeId).isEqualTo(minFps + i);
- assertThat(modeSpecs.primaryRefreshRateRange.min)
+ assertThat(modeSpecs.primary.physical.min)
.isEqualTo((float) (minFps + i));
- assertThat(modeSpecs.primaryRefreshRateRange.max)
+ assertThat(modeSpecs.primary.physical.max)
.isEqualTo((float) (maxFps - i));
+ if (frameRateIsRefreshRate) {
+ assertThat(modeSpecs.primary.render.min)
+ .isEqualTo((float) (minFps + i));
+ } else {
+ assertThat(modeSpecs.primary.render.min).isZero();
+ }
+ assertThat(modeSpecs.primary.render.max)
+ .isEqualTo((float) (maxFps - i));
+ if (priority >= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF) {
+ assertThat(modeSpecs.appRequest.physical.min)
+ .isEqualTo((float) (minFps + i));
+ assertThat(modeSpecs.appRequest.physical.max)
+ .isEqualTo((float) (maxFps - i));
+ if (frameRateIsRefreshRate) {
+ assertThat(modeSpecs.appRequest.render.min).isEqualTo(
+ (float) (minFps + i));
+ } else {
+ assertThat(modeSpecs.appRequest.render.min).isZero();
+ }
+ assertThat(modeSpecs.appRequest.render.max).isEqualTo(
+ (float) (maxFps - i));
+ } else {
+ assertThat(modeSpecs.appRequest.physical.min).isZero();
+ assertThat(modeSpecs.appRequest.physical.max).isPositiveInfinity();
+ assertThat(modeSpecs.appRequest.render.min).isZero();
+ assertThat(modeSpecs.appRequest.render.max).isPositiveInfinity();
+ }
+
}
}
@@ -232,42 +272,53 @@ public class DisplayModeDirectorTest {
// presence of higher priority votes.
{
assertTrue(numPriorities >= 2);
- DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
+ director = createDirectorFromFpsRange(60, 90);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
- votes.put(Vote.MAX_PRIORITY, Vote.forRefreshRates(65, 85));
- votes.put(Vote.MIN_PRIORITY, Vote.forRefreshRates(70, 80));
+ votes.put(Vote.MAX_PRIORITY, Vote.forPhysicalRefreshRates(65, 85));
+ votes.put(Vote.MIN_PRIORITY, Vote.forPhysicalRefreshRates(70, 80));
director.injectVotesByDisplay(votesByDisplay);
modeSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(modeSpecs.baseModeId).isEqualTo(70);
- assertThat(modeSpecs.primaryRefreshRateRange.min).isEqualTo(70f);
- assertThat(modeSpecs.primaryRefreshRateRange.max).isEqualTo(80f);
+ assertThat(modeSpecs.primary.physical.min).isEqualTo(70f);
+ assertThat(modeSpecs.primary.physical.max).isEqualTo(80f);
}
}
@Test
- public void testVotingWithFloatingPointErrors() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testVotingWithFloatingPointErrors(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
DisplayModeDirector director = createDirectorFromFpsRange(50, 90);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
float error = FLOAT_TOLERANCE / 4;
- votes.put(Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE, Vote.forRefreshRates(0, 60));
+ votes.put(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(0, 60));
votes.put(Vote.PRIORITY_APP_REQUEST_SIZE,
- Vote.forRefreshRates(60 + error, 60 + error));
+ Vote.forPhysicalRefreshRates(60 + error, 60 + error));
votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
- Vote.forRefreshRates(60 - error, 60 - error));
+ Vote.forPhysicalRefreshRates(60 - error, 60 - error));
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.baseModeId).isEqualTo(60);
}
@Test
- public void testFlickerHasLowerPriorityThanUserAndRangeIsSingle() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testFlickerHasLowerPriorityThanUserAndRangeIsSingle(
+ boolean frameRateIsRefreshRate) {
assertTrue(Vote.PRIORITY_FLICKER_REFRESH_RATE
< Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
assertTrue(Vote.PRIORITY_FLICKER_REFRESH_RATE
@@ -276,6 +327,7 @@ public class DisplayModeDirectorTest {
assertTrue(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH
> Vote.PRIORITY_LOW_POWER_MODE);
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
Display.Mode[] modes = new Display.Mode[4];
modes[0] = new Display.Mode(
/*modeId=*/1, /*width=*/1000, /*height=*/1000, 60);
@@ -295,14 +347,14 @@ public class DisplayModeDirectorTest {
Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate()));
votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(),
appRequestedMode.getPhysicalHeight()));
- votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forRefreshRates(60, 60));
+ votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(60, 60));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching());
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(2);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.primaryRefreshRateRange.max)
- .isWithin(FLOAT_TOLERANCE).of(desiredSpecs.primaryRefreshRateRange.min);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.max)
+ .isWithin(FLOAT_TOLERANCE).of(desiredSpecs.primary.physical.min);
votes.clear();
appRequestedMode = modes[3];
@@ -310,14 +362,14 @@ public class DisplayModeDirectorTest {
Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate()));
votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(),
appRequestedMode.getPhysicalHeight()));
- votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forRefreshRates(90, 90));
+ votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(90, 90));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching());
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(4);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(desiredSpecs.primaryRefreshRateRange.max)
- .isWithin(FLOAT_TOLERANCE).of(desiredSpecs.primaryRefreshRateRange.min);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.physical.max)
+ .isWithin(FLOAT_TOLERANCE).of(desiredSpecs.primary.physical.min);
votes.clear();
appRequestedMode = modes[3];
@@ -325,14 +377,14 @@ public class DisplayModeDirectorTest {
Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate()));
votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(),
appRequestedMode.getPhysicalHeight()));
- votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forRefreshRates(60, 60));
+ votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(60, 60));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching());
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(4);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(desiredSpecs.primaryRefreshRateRange.max)
- .isWithin(FLOAT_TOLERANCE).of(desiredSpecs.primaryRefreshRateRange.min);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.physical.max)
+ .isWithin(FLOAT_TOLERANCE).of(desiredSpecs.primary.physical.min);
votes.clear();
appRequestedMode = modes[1];
@@ -340,22 +392,28 @@ public class DisplayModeDirectorTest {
Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate()));
votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(),
appRequestedMode.getPhysicalHeight()));
- votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forRefreshRates(90, 90));
+ votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(90, 90));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching());
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(2);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.primaryRefreshRateRange.max)
- .isWithin(FLOAT_TOLERANCE).of(desiredSpecs.primaryRefreshRateRange.min);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.max)
+ .isWithin(FLOAT_TOLERANCE).of(desiredSpecs.primary.physical.min);
}
@Test
- public void testLPMHasHigherPriorityThanUser() {
- assertTrue(Vote.PRIORITY_LOW_POWER_MODE > Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
- assertTrue(Vote.PRIORITY_LOW_POWER_MODE > Vote.PRIORITY_APP_REQUEST_SIZE);
-
-
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testLPMHasHigherPriorityThanUser(boolean frameRateIsRefreshRate) {
+ assertTrue(Vote.PRIORITY_LOW_POWER_MODE
+ > Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
+ assertTrue(Vote.PRIORITY_LOW_POWER_MODE
+ > Vote.PRIORITY_APP_REQUEST_SIZE);
+
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
Display.Mode[] modes = new Display.Mode[4];
modes[0] = new Display.Mode(
/*modeId=*/1, /*width=*/1000, /*height=*/1000, 60);
@@ -375,12 +433,18 @@ public class DisplayModeDirectorTest {
Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate()));
votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(),
appRequestedMode.getPhysicalHeight()));
- votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(60, 60));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(60, 60));
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(2);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
+ } else {
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ }
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
votes.clear();
appRequestedMode = modes[3];
@@ -388,12 +452,18 @@ public class DisplayModeDirectorTest {
Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate()));
votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(),
appRequestedMode.getPhysicalHeight()));
- votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(90, 90));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(90, 90));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(4);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(90);
+ } else {
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ }
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(90);
votes.clear();
appRequestedMode = modes[3];
@@ -401,12 +471,18 @@ public class DisplayModeDirectorTest {
Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate()));
votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(),
appRequestedMode.getPhysicalHeight()));
- votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(60, 60));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(60, 60));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(2);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
+ } else {
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ }
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
votes.clear();
appRequestedMode = modes[1];
@@ -414,26 +490,37 @@ public class DisplayModeDirectorTest {
Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate()));
votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(),
appRequestedMode.getPhysicalHeight()));
- votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(90, 90));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(90, 90));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(4);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(90);
+ } else {
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ }
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(90);
}
@Test
- public void testAppRequestRefreshRateRange() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testAppRequestRefreshRateRange(boolean frameRateIsRefreshRate) {
// Confirm that the app request range doesn't include flicker or min refresh rate settings,
// but does include everything else.
assertTrue(
Vote.PRIORITY_FLICKER_REFRESH_RATE
< Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
- assertTrue(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE
+ assertTrue(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE
< Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
- assertTrue(Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE
+ assertTrue(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE
>= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
Display.Mode[] modes = new Display.Mode[3];
modes[0] = new Display.Mode(
/*modeId=*/60, /*width=*/1000, /*height=*/1000, 60);
@@ -446,25 +533,25 @@ public class DisplayModeDirectorTest {
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
- votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forRefreshRates(60, 60));
+ votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(60, 60));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching());
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(60);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.appRequestRefreshRateRange.min).isAtMost(60f);
- assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f);
+ assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f);
- votes.put(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE,
- Vote.forRefreshRates(90, Float.POSITIVE_INFINITY));
+ votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(90, Float.POSITIVE_INFINITY));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(90);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isAtLeast(90f);
- assertThat(desiredSpecs.appRequestRefreshRateRange.min).isAtMost(60f);
- assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.physical.max).isAtLeast(90f);
+ assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f);
+ assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f);
Display.Mode appRequestedMode = modes[1];
votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
@@ -474,25 +561,28 @@ public class DisplayModeDirectorTest {
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(75);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(75);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(75);
- assertThat(desiredSpecs.appRequestRefreshRateRange.min).isAtMost(60f);
- assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(75);
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(75);
+ assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f);
+ assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f);
}
void verifySpecsWithRefreshRateSettings(DisplayModeDirector director, float minFps,
- float peakFps, float defaultFps, float primaryMin, float primaryMax,
- float appRequestMin, float appRequestMax) {
+ float peakFps, float defaultFps, RefreshRateRanges primary,
+ RefreshRateRanges appRequest) {
DesiredDisplayModeSpecs specs = director.getDesiredDisplayModeSpecsWithInjectedFpsSettings(
minFps, peakFps, defaultFps);
- assertThat(specs.primaryRefreshRateRange.min).isEqualTo(primaryMin);
- assertThat(specs.primaryRefreshRateRange.max).isEqualTo(primaryMax);
- assertThat(specs.appRequestRefreshRateRange.min).isEqualTo(appRequestMin);
- assertThat(specs.appRequestRefreshRateRange.max).isEqualTo(appRequestMax);
+ assertThat(specs.primary).isEqualTo(primary);
+ assertThat(specs.appRequest).isEqualTo(appRequest);
}
@Test
- public void testSpecsFromRefreshRateSettings() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testSpecsFromRefreshRateSettings(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
// Confirm that, with varying settings for min, peak, and default refresh rate,
// DesiredDisplayModeSpecs is calculated correctly.
float[] refreshRates = {30.f, 60.f, 90.f, 120.f, 150.f};
@@ -500,17 +590,56 @@ public class DisplayModeDirectorTest {
createDirectorFromRefreshRateArray(refreshRates, /*baseModeId=*/0);
float inf = Float.POSITIVE_INFINITY;
- verifySpecsWithRefreshRateSettings(director, 0, 0, 0, 0, inf, 0, inf);
- verifySpecsWithRefreshRateSettings(director, 0, 0, 90, 0, 90, 0, inf);
- verifySpecsWithRefreshRateSettings(director, 0, 90, 0, 0, 90, 0, 90);
- verifySpecsWithRefreshRateSettings(director, 0, 90, 60, 0, 60, 0, 90);
- verifySpecsWithRefreshRateSettings(director, 0, 90, 120, 0, 90, 0, 90);
- verifySpecsWithRefreshRateSettings(director, 90, 0, 0, 90, inf, 0, inf);
- verifySpecsWithRefreshRateSettings(director, 90, 0, 120, 90, 120, 0, inf);
- verifySpecsWithRefreshRateSettings(director, 90, 0, 60, 90, inf, 0, inf);
- verifySpecsWithRefreshRateSettings(director, 90, 120, 0, 90, 120, 0, 120);
- verifySpecsWithRefreshRateSettings(director, 90, 60, 0, 90, 90, 0, 90);
- verifySpecsWithRefreshRateSettings(director, 60, 120, 90, 60, 90, 0, 120);
+ RefreshRateRange rangeAll = new RefreshRateRange(0, inf);
+ RefreshRateRange range0to60 = new RefreshRateRange(0, 60);
+ RefreshRateRange range0to90 = new RefreshRateRange(0, 90);
+ RefreshRateRange range0to120 = new RefreshRateRange(0, 120);
+ RefreshRateRange range60to90 = new RefreshRateRange(60, 90);
+ RefreshRateRange range90to90 = new RefreshRateRange(90, 90);
+ RefreshRateRange range90to120 = new RefreshRateRange(90, 120);
+ RefreshRateRange range60toInf = new RefreshRateRange(60, inf);
+ RefreshRateRange range90toInf = new RefreshRateRange(90, inf);
+
+ RefreshRateRanges frameRateAll = new RefreshRateRanges(rangeAll, rangeAll);
+ RefreshRateRanges frameRate90toInf = new RefreshRateRanges(range90toInf, range90toInf);
+ RefreshRateRanges frameRate0to60;
+ RefreshRateRanges frameRate0to90;
+ RefreshRateRanges frameRate0to120;
+ RefreshRateRanges frameRate60to90;
+ RefreshRateRanges frameRate90to90;
+ RefreshRateRanges frameRate90to120;
+ if (frameRateIsRefreshRate) {
+ frameRate0to60 = new RefreshRateRanges(range0to60, range0to60);
+ frameRate0to90 = new RefreshRateRanges(range0to90, range0to90);
+ frameRate0to120 = new RefreshRateRanges(range0to120, range0to120);
+ frameRate60to90 = new RefreshRateRanges(range60to90, range60to90);
+ frameRate90to90 = new RefreshRateRanges(range90to90, range90to90);
+ frameRate90to120 = new RefreshRateRanges(range90to120, range90to120);
+ } else {
+ frameRate0to60 = new RefreshRateRanges(rangeAll, range0to60);
+ frameRate0to90 = new RefreshRateRanges(rangeAll, range0to90);
+ frameRate0to120 = new RefreshRateRanges(rangeAll, range0to120);
+ frameRate60to90 = new RefreshRateRanges(range60toInf, range60to90);
+ frameRate90to90 = new RefreshRateRanges(range90toInf, range90to90);
+ frameRate90to120 = new RefreshRateRanges(range90toInf, range90to120);
+ }
+
+ verifySpecsWithRefreshRateSettings(director, 0, 0, 0, frameRateAll, frameRateAll);
+ verifySpecsWithRefreshRateSettings(director, 0, 0, 90, frameRate0to90, frameRateAll);
+ verifySpecsWithRefreshRateSettings(director, 0, 90, 0, frameRate0to90, frameRate0to90);
+ verifySpecsWithRefreshRateSettings(director, 0, 90, 60, frameRate0to60, frameRate0to90);
+ verifySpecsWithRefreshRateSettings(director, 0, 90, 120, frameRate0to90,
+ frameRate0to90);
+ verifySpecsWithRefreshRateSettings(director, 90, 0, 0, frameRate90toInf, frameRateAll);
+ verifySpecsWithRefreshRateSettings(director, 90, 0, 120, frameRate90to120,
+ frameRateAll);
+ verifySpecsWithRefreshRateSettings(director, 90, 0, 60, frameRate90toInf, frameRateAll);
+ verifySpecsWithRefreshRateSettings(director, 90, 120, 0, frameRate90to120,
+ frameRate0to120);
+ verifySpecsWithRefreshRateSettings(director, 90, 60, 0, frameRate90to90,
+ frameRate0to90);
+ verifySpecsWithRefreshRateSettings(director, 60, 120, 90, frameRate60to90,
+ frameRate0to120);
}
void verifyBrightnessObserverCall(DisplayModeDirector director, float minFps, float peakFps,
@@ -523,7 +652,12 @@ public class DisplayModeDirectorTest {
}
@Test
- public void testBrightnessObserverCallWithRefreshRateSettings() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testBrightnessObserverCallWithRefreshRateSettings(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
// Confirm that, with varying settings for min, peak, and default refresh rate, we make the
// correct call to the brightness observer.
float[] refreshRates = {60.f, 90.f, 120.f};
@@ -538,7 +672,12 @@ public class DisplayModeDirectorTest {
}
@Test
- public void testVotingWithAlwaysRespectAppRequest() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testVotingWithAlwaysRespectAppRequest(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
Display.Mode[] modes = new Display.Mode[3];
modes[0] = new Display.Mode(
/*modeId=*/50, /*width=*/1000, /*height=*/1000, 50);
@@ -549,61 +688,94 @@ public class DisplayModeDirectorTest {
DisplayModeDirector director = createDirectorFromModeArray(modes, modes[0]);
-
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
- votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forRefreshRates(0, 60));
- votes.put(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE, Vote.forRefreshRates(60, 90));
+ votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(0, 60));
+ votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(60, 90));
Display.Mode appRequestedMode = modes[2];
votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate()));
- votes.put(Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE, Vote.forRefreshRates(60, 60));
- votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(0, 60));
+ votes.put(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(60, 60));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60));
director.injectVotesByDisplay(votesByDisplay);
assertThat(director.shouldAlwaysRespectAppRequestedMode()).isFalse();
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
+ } else {
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ }
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.baseModeId).isEqualTo(60);
director.setShouldAlwaysRespectAppRequestedMode(true);
assertThat(director.shouldAlwaysRespectAppRequestedMode()).isTrue();
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isAtMost(50);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isAtLeast(90);
+ assertThat(desiredSpecs.primary.physical.min).isAtMost(50);
+ assertThat(desiredSpecs.primary.physical.max).isAtLeast(90);
+ assertThat(desiredSpecs.primary.render.min).isAtMost(50);
+ assertThat(desiredSpecs.primary.render.max).isAtLeast(90);
assertThat(desiredSpecs.baseModeId).isEqualTo(90);
director.setShouldAlwaysRespectAppRequestedMode(false);
assertThat(director.shouldAlwaysRespectAppRequestedMode()).isFalse();
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
+ } else {
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ }
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.baseModeId).isEqualTo(60);
}
@Test
- public void testVotingWithSwitchingTypeNone() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testVotingWithSwitchingTypeNone(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
DisplayModeDirector director = createDirectorFromFpsRange(0, 90);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
- votes.put(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE, Vote.forRefreshRates(30, 90));
- votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(0, 60));
-
+ votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(30, 90));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60));
director.injectVotesByDisplay(votesByDisplay);
assertThat(director.getModeSwitchingType())
.isNotEqualTo(DisplayManager.SWITCHING_TYPE_NONE);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(30);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.appRequestRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(0);
- assertThat(desiredSpecs.appRequestRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(30);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
+ } else {
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ }
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(30);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(0);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(
+ 60);
+ } else {
+ assertThat(desiredSpecs.appRequest.physical.max).isPositiveInfinity();
+ }
+ assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(0);
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.baseModeId).isEqualTo(30);
director.setModeSwitchingType(DisplayManager.SWITCHING_TYPE_NONE);
@@ -611,10 +783,14 @@ public class DisplayModeDirectorTest {
.isEqualTo(DisplayManager.SWITCHING_TYPE_NONE);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(30);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(30);
- assertThat(desiredSpecs.appRequestRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(30);
- assertThat(desiredSpecs.appRequestRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(30);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(30);
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(30);
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(30);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(30);
+ assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(30);
+ assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(30);
+ assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(30);
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(30);
assertThat(desiredSpecs.baseModeId).isEqualTo(30);
}
@@ -641,7 +817,12 @@ public class DisplayModeDirectorTest {
}
@Test
- public void testDefaultDisplayModeIsSelectedIfAvailable() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testDefaultDisplayModeIsSelectedIfAvailable(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
final float[] refreshRates = new float[]{24f, 25f, 30f, 60f, 90f};
final int defaultModeId = 3;
DisplayModeDirector director = createDirectorFromRefreshRateArray(
@@ -778,7 +959,7 @@ public class DisplayModeDirectorTest {
sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 20 /*lux*/));
Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE);
- assertVoteForRefreshRate(vote, 90 /*fps*/);
+ assertVoteForPhysicalRefreshRate(vote, 90 /*fps*/);
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH);
assertThat(vote).isNotNull();
assertThat(vote.disableRefreshRateSwitching).isTrue();
@@ -847,7 +1028,7 @@ public class DisplayModeDirectorTest {
sensorListener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000));
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE);
- assertVoteForRefreshRate(vote, 60 /*fps*/);
+ assertVoteForPhysicalRefreshRate(vote, 60 /*fps*/);
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH);
assertThat(vote).isNotNull();
assertThat(vote.disableRefreshRateSwitching).isTrue();
@@ -923,12 +1104,17 @@ public class DisplayModeDirectorTest {
}
@Test
- public void testAppRequestMinRefreshRate() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testAppRequestMinRefreshRate(boolean frameRateIsRefreshRate) {
// Confirm that the app min request range doesn't include flicker or min refresh rate
// settings but does include everything else.
- assertTrue(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE
+ assertTrue(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE
>= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
Display.Mode[] modes = new Display.Mode[3];
modes[0] = new Display.Mode(
/*modeId=*/60, /*width=*/1000, /*height=*/1000, 60);
@@ -942,38 +1128,42 @@ public class DisplayModeDirectorTest {
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching());
- votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forRefreshRates(60, 60));
+ votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(60, 60));
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.appRequestRefreshRateRange.min).isAtMost(60f);
- assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f);
+ assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f);
- votes.put(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE,
- Vote.forRefreshRates(90, Float.POSITIVE_INFINITY));
+ votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(90, Float.POSITIVE_INFINITY));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isAtLeast(90f);
- assertThat(desiredSpecs.appRequestRefreshRateRange.min).isAtMost(60f);
- assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.physical.max).isAtLeast(90f);
+ assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f);
+ assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f);
- votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE,
- Vote.forRefreshRates(75, Float.POSITIVE_INFINITY));
+ votes.put(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE,
+ Vote.forRenderFrameRates(75, Float.POSITIVE_INFINITY));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(desiredSpecs.appRequestRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(75);
- assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(75);
+ assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f);
}
@Test
- public void testAppRequestMaxRefreshRate() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testAppRequestMaxRefreshRate(boolean frameRateIsRefreshRate) {
// Confirm that the app max request range doesn't include flicker or min refresh rate
// settings but does include everything else.
- assertTrue(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE
+ assertTrue(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE
>= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
Display.Mode[] modes = new Display.Mode[3];
@@ -984,47 +1174,85 @@ public class DisplayModeDirectorTest {
modes[2] = new Display.Mode(
/*modeId=*/90, /*width=*/1000, /*height=*/1000, 90);
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
DisplayModeDirector director = createDirectorFromModeArray(modes, modes[1]);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching());
- votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forRefreshRates(60, 60));
+ votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forPhysicalRefreshRates(60, 60));
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.appRequestRefreshRateRange.min).isAtMost(60f);
- assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(60);
+ } else {
+ assertThat(desiredSpecs.primary.render.min).isZero();
+ }
+ assertThat(desiredSpecs.primary.render.max).isAtMost(60);
+ assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f);
+ assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.appRequest.render.min).isAtMost(60f);
+ } else {
+ assertThat(desiredSpecs.appRequest.render.min).isZero();
+ }
+ assertThat(desiredSpecs.appRequest.render.max).isAtLeast(90f);
- votes.put(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE,
- Vote.forRefreshRates(90, Float.POSITIVE_INFINITY));
+ votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(90, Float.POSITIVE_INFINITY));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isAtLeast(90f);
- assertThat(desiredSpecs.appRequestRefreshRateRange.min).isAtMost(60f);
- assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f);
-
- votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE, Vote.forRefreshRates(0, 75));
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.render.max).isAtLeast(90f);
+ assertThat(desiredSpecs.appRequest.physical.min).isAtMost(60f);
+ assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f);
+ assertThat(desiredSpecs.appRequest.render.min).isAtMost(60f);
+ assertThat(desiredSpecs.appRequest.render.max).isAtLeast(90f);
+
+ votes.put(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE,
+ Vote.forRenderFrameRates(0, 75));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(75);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(75);
- assertThat(desiredSpecs.appRequestRefreshRateRange.min).isZero();
- assertThat(desiredSpecs.appRequestRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(75);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(75);
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(75);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(75);
+ } else {
+ assertThat(desiredSpecs.primary.render.min).isZero();
+ }
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(75);
+ assertThat(desiredSpecs.appRequest.physical.min).isZero();
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(
+ 75);
+ } else {
+ assertThat(desiredSpecs.appRequest.physical.max).isAtLeast(90f);
+ }
+ assertThat(desiredSpecs.appRequest.render.min).isZero();
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(75);
}
@Test
- public void testAppRequestObserver_modeId() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testAppRequestObserver_modeId(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
director.getAppRequestObserver().setAppRequest(DISPLAY_ID, 60, 0, 0);
Vote appRequestRefreshRate =
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
assertNotNull(appRequestRefreshRate);
- assertThat(appRequestRefreshRate.refreshRateRange.min).isZero();
- assertThat(appRequestRefreshRate.refreshRateRange.max).isPositiveInfinity();
+ assertThat(appRequestRefreshRate.refreshRateRanges.physical.min).isZero();
+ assertThat(appRequestRefreshRate.refreshRateRanges.physical.max).isPositiveInfinity();
+ assertThat(appRequestRefreshRate.refreshRateRanges.render.min).isZero();
+ assertThat(appRequestRefreshRate.refreshRateRanges.render.max).isPositiveInfinity();
assertThat(appRequestRefreshRate.disableRefreshRateSwitching).isFalse();
assertThat(appRequestRefreshRate.baseModeRefreshRate).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(appRequestRefreshRate.height).isEqualTo(INVALID_SIZE);
@@ -1032,15 +1260,17 @@ public class DisplayModeDirectorTest {
Vote appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE);
assertNotNull(appRequestSize);
- assertThat(appRequestSize.refreshRateRange.min).isZero();
- assertThat(appRequestSize.refreshRateRange.max).isPositiveInfinity();
+ assertThat(appRequestSize.refreshRateRanges.physical.min).isZero();
+ assertThat(appRequestSize.refreshRateRanges.physical.max).isPositiveInfinity();
+ assertThat(appRequestSize.refreshRateRanges.render.min).isZero();
+ assertThat(appRequestSize.refreshRateRanges.render.max).isPositiveInfinity();
assertThat(appRequestSize.disableRefreshRateSwitching).isFalse();
assertThat(appRequestSize.baseModeRefreshRate).isZero();
assertThat(appRequestSize.height).isEqualTo(1000);
assertThat(appRequestSize.width).isEqualTo(1000);
Vote appRequestRefreshRateRange =
- director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE);
+ director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
assertNull(appRequestRefreshRateRange);
director.getAppRequestObserver().setAppRequest(DISPLAY_ID, 90, 0, 0);
@@ -1048,8 +1278,10 @@ public class DisplayModeDirectorTest {
appRequestRefreshRate =
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
assertNotNull(appRequestRefreshRate);
- assertThat(appRequestRefreshRate.refreshRateRange.min).isZero();
- assertThat(appRequestRefreshRate.refreshRateRange.max).isPositiveInfinity();
+ assertThat(appRequestRefreshRate.refreshRateRanges.physical.min).isZero();
+ assertThat(appRequestRefreshRate.refreshRateRanges.physical.max).isPositiveInfinity();
+ assertThat(appRequestRefreshRate.refreshRateRanges.render.min).isZero();
+ assertThat(appRequestRefreshRate.refreshRateRanges.render.max).isPositiveInfinity();
assertThat(appRequestRefreshRate.disableRefreshRateSwitching).isFalse();
assertThat(appRequestRefreshRate.baseModeRefreshRate).isWithin(FLOAT_TOLERANCE).of(90);
assertThat(appRequestRefreshRate.height).isEqualTo(INVALID_SIZE);
@@ -1057,18 +1289,25 @@ public class DisplayModeDirectorTest {
appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE);
assertNotNull(appRequestSize);
- assertThat(appRequestSize.refreshRateRange.min).isZero();
- assertThat(appRequestSize.refreshRateRange.max).isPositiveInfinity();
+ assertThat(appRequestSize.refreshRateRanges.physical.min).isZero();
+ assertThat(appRequestSize.refreshRateRanges.physical.max).isPositiveInfinity();
+ assertThat(appRequestSize.refreshRateRanges.render.min).isZero();
+ assertThat(appRequestSize.refreshRateRanges.render.max).isPositiveInfinity();
assertThat(appRequestSize.height).isEqualTo(1000);
assertThat(appRequestSize.width).isEqualTo(1000);
appRequestRefreshRateRange =
- director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE);
+ director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
assertNull(appRequestRefreshRateRange);
}
@Test
- public void testAppRequestObserver_minRefreshRate() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testAppRequestObserver_minRefreshRate(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 60, 0);
Vote appRequestRefreshRate =
@@ -1079,11 +1318,20 @@ public class DisplayModeDirectorTest {
assertNull(appRequestSize);
Vote appRequestRefreshRateRange =
- director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE);
+ director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
assertNotNull(appRequestRefreshRateRange);
- assertThat(appRequestRefreshRateRange.refreshRateRange.min)
+ if (frameRateIsRefreshRate) {
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min)
+ .isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max).isAtLeast(90);
+ } else {
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero();
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
+ .isPositiveInfinity();
+ }
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min)
.isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(appRequestRefreshRateRange.refreshRateRange.max).isAtLeast(90);
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.render.max).isAtLeast(90);
assertThat(appRequestRefreshRateRange.height).isEqualTo(INVALID_SIZE);
assertThat(appRequestRefreshRateRange.width).isEqualTo(INVALID_SIZE);
@@ -1096,17 +1344,32 @@ public class DisplayModeDirectorTest {
assertNull(appRequestSize);
appRequestRefreshRateRange =
- director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE);
+ director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
assertNotNull(appRequestRefreshRateRange);
- assertThat(appRequestRefreshRateRange.refreshRateRange.min)
+ if (frameRateIsRefreshRate) {
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isWithin(
+ FLOAT_TOLERANCE).of(90);
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max).isAtLeast(90);
+ } else {
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero();
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
+ .isPositiveInfinity();
+ }
+
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min)
.isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(appRequestRefreshRateRange.refreshRateRange.max).isAtLeast(90);
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.render.max).isAtLeast(90);
assertThat(appRequestRefreshRateRange.height).isEqualTo(INVALID_SIZE);
assertThat(appRequestRefreshRateRange.width).isEqualTo(INVALID_SIZE);
}
@Test
- public void testAppRequestObserver_maxRefreshRate() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testAppRequestObserver_maxRefreshRate(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 0, 90);
Vote appRequestRefreshRate =
@@ -1117,10 +1380,19 @@ public class DisplayModeDirectorTest {
assertNull(appRequestSize);
Vote appRequestRefreshRateRange =
- director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE);
+ director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
assertNotNull(appRequestRefreshRateRange);
- assertThat(appRequestRefreshRateRange.refreshRateRange.min).isZero();
- assertThat(appRequestRefreshRateRange.refreshRateRange.max)
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero();
+ if (frameRateIsRefreshRate) {
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
+ .isWithin(FLOAT_TOLERANCE).of(90);
+ } else {
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
+ .isPositiveInfinity();
+ }
+
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min).isZero();
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.render.max)
.isWithin(FLOAT_TOLERANCE).of(90);
assertThat(appRequestRefreshRateRange.height).isEqualTo(INVALID_SIZE);
assertThat(appRequestRefreshRateRange.width).isEqualTo(INVALID_SIZE);
@@ -1134,10 +1406,19 @@ public class DisplayModeDirectorTest {
assertNull(appRequestSize);
appRequestRefreshRateRange =
- director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE);
+ director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
assertNotNull(appRequestRefreshRateRange);
- assertThat(appRequestRefreshRateRange.refreshRateRange.min).isZero();
- assertThat(appRequestRefreshRateRange.refreshRateRange.max)
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero();
+ if (frameRateIsRefreshRate) {
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
+ .isWithin(FLOAT_TOLERANCE).of(60);
+ } else {
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
+ .isPositiveInfinity();
+ }
+
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min).isZero();
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.render.max)
.isWithin(FLOAT_TOLERANCE).of(60);
assertThat(appRequestRefreshRateRange.height).isEqualTo(INVALID_SIZE);
assertThat(appRequestRefreshRateRange.width).isEqualTo(INVALID_SIZE);
@@ -1155,20 +1436,27 @@ public class DisplayModeDirectorTest {
assertNull(appRequestSize);
Vote appRequestRefreshRateRange =
- director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE);
+ director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
assertNull(appRequestRefreshRateRange);
}
@Test
- public void testAppRequestObserver_modeIdAndRefreshRateRange() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testAppRequestObserver_modeIdAndRefreshRateRange(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
director.getAppRequestObserver().setAppRequest(DISPLAY_ID, 60, 90, 90);
Vote appRequestRefreshRate =
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
assertNotNull(appRequestRefreshRate);
- assertThat(appRequestRefreshRate.refreshRateRange.min).isZero();
- assertThat(appRequestRefreshRate.refreshRateRange.max).isPositiveInfinity();
+ assertThat(appRequestRefreshRate.refreshRateRanges.physical.min).isZero();
+ assertThat(appRequestRefreshRate.refreshRateRanges.physical.max).isPositiveInfinity();
+ assertThat(appRequestRefreshRate.refreshRateRanges.render.min).isZero();
+ assertThat(appRequestRefreshRate.refreshRateRanges.render.max).isPositiveInfinity();
assertThat(appRequestRefreshRate.disableRefreshRateSwitching).isFalse();
assertThat(appRequestRefreshRate.baseModeRefreshRate).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(appRequestRefreshRate.height).isEqualTo(INVALID_SIZE);
@@ -1177,24 +1465,41 @@ public class DisplayModeDirectorTest {
Vote appRequestSize =
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE);
assertNotNull(appRequestSize);
- assertThat(appRequestSize.refreshRateRange.min).isZero();
- assertThat(appRequestSize.refreshRateRange.max).isPositiveInfinity();
+ assertThat(appRequestSize.refreshRateRanges.physical.min).isZero();
+ assertThat(appRequestSize.refreshRateRanges.physical.max).isPositiveInfinity();
+ assertThat(appRequestSize.refreshRateRanges.render.min).isZero();
+ assertThat(appRequestSize.refreshRateRanges.render.max).isPositiveInfinity();
assertThat(appRequestSize.height).isEqualTo(1000);
assertThat(appRequestSize.width).isEqualTo(1000);
Vote appRequestRefreshRateRange =
- director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE);
+ director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE);
assertNotNull(appRequestRefreshRateRange);
- assertThat(appRequestRefreshRateRange.refreshRateRange.max)
+ if (frameRateIsRefreshRate) {
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min)
+ .isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
+ .isWithin(FLOAT_TOLERANCE).of(90);
+ } else {
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.min).isZero();
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.physical.max)
+ .isPositiveInfinity();
+ }
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.render.min)
.isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(appRequestRefreshRateRange.refreshRateRange.max)
+ assertThat(appRequestRefreshRateRange.refreshRateRanges.render.max)
.isWithin(FLOAT_TOLERANCE).of(90);
assertThat(appRequestRefreshRateRange.height).isEqualTo(INVALID_SIZE);
assertThat(appRequestRefreshRateRange.width).isEqualTo(INVALID_SIZE);
}
@Test
- public void testAppRequestsIsTheDefaultMode() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testAppRequestsIsTheDefaultMode(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
Display.Mode[] modes = new Display.Mode[2];
modes[0] = new Display.Mode(
/*modeId=*/1, /*width=*/1000, /*height=*/1000, 60);
@@ -1204,8 +1509,8 @@ public class DisplayModeDirectorTest {
DisplayModeDirector director = createDirectorFromModeArray(modes, modes[0]);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(1);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isAtMost(60);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isAtLeast(90);
+ assertThat(desiredSpecs.primary.physical.min).isAtMost(60);
+ assertThat(desiredSpecs.primary.physical.max).isAtLeast(90);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
@@ -1214,105 +1519,148 @@ public class DisplayModeDirectorTest {
votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
Vote.forBaseModeRefreshRate(appRequestedMode.getRefreshRate()));
votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(appRequestedMode.getPhysicalWidth(),
- appRequestedMode.getPhysicalHeight()));
+ appRequestedMode.getPhysicalHeight()));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(2);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isAtMost(60);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isAtLeast(90);
+ assertThat(desiredSpecs.primary.physical.min).isAtMost(60);
+ assertThat(desiredSpecs.primary.physical.max).isAtLeast(90);
}
@Test
- public void testDisableRefreshRateSwitchingVote() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testDisableRefreshRateSwitchingVote(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
DisplayModeDirector director = createDirectorFromFpsRange(50, 90);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
- votes.put(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE,
- Vote.forRefreshRates(90, Float.POSITIVE_INFINITY));
+ votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(90, Float.POSITIVE_INFINITY));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching());
- votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(0, 60));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60));
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(50);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(50);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(50);
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(50);
assertThat(desiredSpecs.baseModeId).isEqualTo(50);
votes.clear();
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE,
- Vote.forRefreshRates(70, Float.POSITIVE_INFINITY));
- votes.put(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE,
- Vote.forRefreshRates(80, Float.POSITIVE_INFINITY));
+ Vote.forPhysicalRefreshRates(70, Float.POSITIVE_INFINITY));
+ votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(80, Float.POSITIVE_INFINITY));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching());
- votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(0, 90));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 90));
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(80);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(80);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(80);
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(80);
assertThat(desiredSpecs.baseModeId).isEqualTo(80);
votes.clear();
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE,
- Vote.forRefreshRates(90, Float.POSITIVE_INFINITY));
- votes.put(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE,
- Vote.forRefreshRates(80, Float.POSITIVE_INFINITY));
+ Vote.forPhysicalRefreshRates(90, Float.POSITIVE_INFINITY));
+ votes.put(Vote.PRIORITY_USER_SETTING_MIN_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(80, Float.POSITIVE_INFINITY));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching());
- votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(0, 90));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 90));
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(90);
assertThat(desiredSpecs.baseModeId).isEqualTo(90);
}
@Test
- public void testBaseModeIdInPrimaryRange() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testBaseModeIdInPrimaryRange(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
DisplayModeDirector director = createDirectorFromFpsRange(50, 90);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
Vote.forBaseModeRefreshRate(70));
- votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(0, 60));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60));
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(0);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
- assertThat(desiredSpecs.baseModeId).isEqualTo(50);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(0);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.baseModeId).isEqualTo(50);
+ } else {
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ assertThat(desiredSpecs.baseModeId).isEqualTo(70);
+ }
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(0);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
Vote.forBaseModeRefreshRate(55));
- votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(0, 60));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(0);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(0);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
+ } else {
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ }
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(0);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.baseModeId).isEqualTo(55);
votes.clear();
- votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE, Vote.forRefreshRates(0, 52));
+ votes.put(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE,
+ Vote.forRenderFrameRates(0, 52));
votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
Vote.forBaseModeRefreshRate(55));
- votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(0, 60));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(0);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(0);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(60);
+ } else {
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(52);
+ }
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(0);
assertThat(desiredSpecs.baseModeId).isEqualTo(55);
votes.clear();
- votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE_RANGE, Vote.forRefreshRates(0, 58));
+ votes.put(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE,
+ Vote.forRenderFrameRates(0, 58));
votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
Vote.forBaseModeRefreshRate(55));
- votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(0, 60));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(0, 60));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
- assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(0);
- assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(58);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(0);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(58);
+ } else {
+ assertThat(desiredSpecs.primary.physical.max).isPositiveInfinity();
+ }
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(0);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(58);
assertThat(desiredSpecs.baseModeId).isEqualTo(55);
}
@Test
- public void testStaleAppVote() {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testStaleAppVote(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
Display.Mode[] modes = new Display.Mode[4];
modes[0] = new Display.Mode(
/*modeId=*/1, /*width=*/1000, /*height=*/1000, 60);
@@ -1358,9 +1706,124 @@ public class DisplayModeDirectorTest {
}
@Test
- public void testProximitySensorVoting() throws Exception {
+ @Parameters({
+ "true",
+ "false"
+ })
+ public void testRefreshRateIsSubsetOfFrameRate(boolean frameRateIsRefreshRate) {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(frameRateIsRefreshRate);
+ DisplayModeDirector director = createDirectorFromFpsRange(60, 120);
+ SparseArray<Vote> votes = new SparseArray<>();
+ SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
+ votesByDisplay.put(DISPLAY_ID, votes);
+
+
+ votes.put(Vote.PRIORITY_UDFPS, Vote.forPhysicalRefreshRates(90, 120));
+ director.injectVotesByDisplay(votesByDisplay);
+ DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
+ assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(120);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(90);
+ } else {
+ assertThat(desiredSpecs.appRequest.render.min).isZero();
+ }
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(120);
+
+ votes.clear();
+ votes.put(Vote.PRIORITY_UDFPS, Vote.forPhysicalRefreshRates(90, 120));
+ votes.put(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(0, 60));
+ director.injectVotesByDisplay(votesByDisplay);
+ desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
+ assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(120);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(
+ 120);
+ } else {
+ assertThat(desiredSpecs.appRequest.render.min).isZero();
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60);
+ }
+
+ votes.clear();
+ votes.put(Vote.PRIORITY_UDFPS, Vote.forPhysicalRefreshRates(90, 120));
+ votes.put(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(60, 60));
+ director.injectVotesByDisplay(votesByDisplay);
+ desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
+ assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(120);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(
+ 120);
+ } else {
+ assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(60);
+ }
+
+ votes.clear();
+ votes.put(Vote.PRIORITY_UDFPS, Vote.forPhysicalRefreshRates(90, 120));
+ votes.put(Vote.PRIORITY_USER_SETTING_PEAK_RENDER_FRAME_RATE,
+ Vote.forRenderFrameRates(140, 140));
+ director.injectVotesByDisplay(votesByDisplay);
+ desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
+ assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(90);
+ assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(120);
+ if (frameRateIsRefreshRate) {
+ assertThat(desiredSpecs.appRequest.render.min).isWithin(FLOAT_TOLERANCE).of(90);
+ } else {
+ assertThat(desiredSpecs.appRequest.render.min).isZero();
+ }
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(120);
+ }
+
+ @Test
+ public void testRenderFrameRateIsAchievableByPhysicalRefreshRate() {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(false);
+ DisplayModeDirector director = createDirectorFromFpsRange(60, 120);
+ SparseArray<Vote> votes = new SparseArray<>();
+ SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
+ votesByDisplay.put(DISPLAY_ID, votes);
+
+
+ votes.put(Vote.PRIORITY_UDFPS, Vote.forPhysicalRefreshRates(120, 120));
+ votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRenderFrameRates(90, 90));
+ director.injectVotesByDisplay(votesByDisplay);
+ DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
+ assertThat(desiredSpecs.appRequest.physical.min).isWithin(FLOAT_TOLERANCE).of(120);
+ assertThat(desiredSpecs.appRequest.physical.max).isWithin(FLOAT_TOLERANCE).of(120);
+ assertThat(desiredSpecs.appRequest.render.min).isZero();
+ assertThat(desiredSpecs.appRequest.render.max).isWithin(FLOAT_TOLERANCE).of(120);
+ }
+
+ @Test
+ public void testRenderFrameRateIsDroppedIfLowerPriorityThenBaseModeRefreshRate() {
+ when(mInjector.renderFrameRateIsPhysicalRefreshRate()).thenReturn(false);
+ DisplayModeDirector director = createDirectorFromFpsRange(60, 120);
+ SparseArray<Vote> votes = new SparseArray<>();
+ SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
+ votesByDisplay.put(DISPLAY_ID, votes);
+ votes.put(Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE,
+ Vote.forRenderFrameRates(120, 120));
+ votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
+ Vote.forBaseModeRefreshRate(90));
+ votes.put(Vote.PRIORITY_PROXIMITY, Vote.forPhysicalRefreshRates(60, 120));
+ director.injectVotesByDisplay(votesByDisplay);
+ DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
+ assertThat(desiredSpecs.primary.physical.min).isWithin(FLOAT_TOLERANCE).of(60);
+ assertThat(desiredSpecs.primary.physical.max).isWithin(FLOAT_TOLERANCE).of(120);
+ assertThat(desiredSpecs.primary.render.min).isWithin(FLOAT_TOLERANCE).of(0);
+ assertThat(desiredSpecs.primary.render.max).isWithin(FLOAT_TOLERANCE).of(120);
+ assertThat(desiredSpecs.baseModeId).isEqualTo(90);
+ }
+
+ @Test
+ public void testProximitySensorVoting() {
DisplayModeDirector director =
- createDirectorFromRefreshRateArray(new float[] {60.f, 90.f}, 0);
+ createDirectorFromRefreshRateArray(new float[]{60.f, 90.f}, 0);
director.start(createMockSensorManager());
ArgumentCaptor<ProximityActiveListener> ProximityCaptor =
@@ -1389,7 +1852,7 @@ public class DisplayModeDirectorTest {
// Set the proximity to active and verify that we added a vote.
proximityListener.onProximityActive(true);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
- assertVoteForRefreshRate(vote, 60.f);
+ assertVoteForPhysicalRefreshRate(vote, 60.f);
// Set the display state to doze and verify that the vote is gone
when(mInjector.isDozeState(any(Display.class))).thenReturn(true);
@@ -1401,7 +1864,7 @@ public class DisplayModeDirectorTest {
when(mInjector.isDozeState(any(Display.class))).thenReturn(false);
displayListener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
- assertVoteForRefreshRate(vote, 60.f);
+ assertVoteForPhysicalRefreshRate(vote, 60.f);
// Set the display state to doze and verify that the vote is gone
when(mInjector.isDozeState(any(Display.class))).thenReturn(true);
@@ -1412,7 +1875,7 @@ public class DisplayModeDirectorTest {
// Remove the display to cause the doze state to be removed
displayListener.onDisplayRemoved(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_PROXIMITY);
- assertVoteForRefreshRate(vote, 60.f);
+ assertVoteForPhysicalRefreshRate(vote, 60.f);
// Turn prox off and verify vote is gone.
proximityListener.onProximityActive(false);
@@ -1456,7 +1919,7 @@ public class DisplayModeDirectorTest {
BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
- assertVoteForRefreshRate(vote, hbmRefreshRate);
+ assertVoteForPhysicalRefreshRate(vote, hbmRefreshRate);
// Turn on HBM, with brightness below the HBM range
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
@@ -1483,7 +1946,7 @@ public class DisplayModeDirectorTest {
BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
- assertVoteForRefreshRate(vote, hbmRefreshRate);
+ assertVoteForPhysicalRefreshRate(vote, hbmRefreshRate);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
@@ -1579,7 +2042,7 @@ public class DisplayModeDirectorTest {
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
- assertVoteForRefreshRate(vote, initialRefreshRate);
+ assertVoteForPhysicalRefreshRate(vote, initialRefreshRate);
// Change refresh rate vote value through DeviceConfig, ensure it takes precedence
final int updatedRefreshRate = 90;
@@ -1589,7 +2052,7 @@ public class DisplayModeDirectorTest {
assertThat(director.getHbmObserver().getRefreshRateInHbmSunlight())
.isEqualTo(updatedRefreshRate);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
- assertVoteForRefreshRate(vote, updatedRefreshRate);
+ assertVoteForPhysicalRefreshRate(vote, updatedRefreshRate);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
@@ -1605,7 +2068,7 @@ public class DisplayModeDirectorTest {
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
- assertVoteForRefreshRate(vote, updatedRefreshRate);
+ assertVoteForPhysicalRefreshRate(vote, updatedRefreshRate);
// Reset DeviceConfig refresh rate, ensure vote falls back to the initial value
mInjector.getDeviceConfig().setRefreshRateInHbmSunlight(0);
@@ -1613,7 +2076,7 @@ public class DisplayModeDirectorTest {
waitForIdleSync();
assertThat(director.getHbmObserver().getRefreshRateInHbmSunlight()).isEqualTo(0);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
- assertVoteForRefreshRate(vote, initialRefreshRate);
+ assertVoteForPhysicalRefreshRate(vote, initialRefreshRate);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
@@ -1693,7 +2156,7 @@ public class DisplayModeDirectorTest {
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
- assertVoteForRefreshRate(vote, 60.0f);
+ assertVoteForPhysicalRefreshRate(vote, 60.0f);
// Turn off HBM
when(mInjector.getBrightnessInfo(DISPLAY_ID)).thenReturn(
@@ -1741,7 +2204,7 @@ public class DisplayModeDirectorTest {
if (Float.isNaN(rr)) {
assertNull(vote);
} else {
- assertVoteForRefreshRate(vote, rr);
+ assertVoteForPhysicalRefreshRate(vote, rr);
}
}
@@ -1817,7 +2280,7 @@ public class DisplayModeDirectorTest {
TRANSITION_POINT, BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE));
listener.onDisplayChanged(DISPLAY_ID);
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_HIGH_BRIGHTNESS_MODE);
- assertVoteForRefreshRate(vote, 60.f);
+ assertVoteForPhysicalRefreshRate(vote, 60.f);
// Turn off HBM
listener.onDisplayRemoved(DISPLAY_ID);
@@ -1845,7 +2308,7 @@ public class DisplayModeDirectorTest {
// Set the skin temperature to critical and verify that we added a vote.
listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_CRITICAL));
vote = director.getVote(DISPLAY_ID, Vote.PRIORITY_SKIN_TEMPERATURE);
- assertVoteForRefreshRateRange(vote, 0f, 60.f);
+ assertVoteForRenderFrameRateRange(vote, 0f, 60.f);
// Set the skin temperature to severe and verify that the vote is gone.
listener.notifyThrottling(getSkinTemp(Temperature.THROTTLING_SEVERE));
@@ -1871,18 +2334,18 @@ public class DisplayModeDirectorTest {
return new Temperature(30.0f, Temperature.TYPE_SKIN, "test_skin_temp", status);
}
- private void assertVoteForRefreshRate(Vote vote, float refreshRate) {
+ private void assertVoteForPhysicalRefreshRate(Vote vote, float refreshRate) {
assertThat(vote).isNotNull();
final RefreshRateRange expectedRange = new RefreshRateRange(refreshRate, refreshRate);
- assertThat(vote.refreshRateRange).isEqualTo(expectedRange);
+ assertThat(vote.refreshRateRanges.physical).isEqualTo(expectedRange);
}
- private void assertVoteForRefreshRateRange(
- Vote vote, float refreshRateLow, float refreshRateHigh) {
+ private void assertVoteForRenderFrameRateRange(
+ Vote vote, float frameRateLow, float frameRateHigh) {
assertThat(vote).isNotNull();
final RefreshRateRange expectedRange =
- new RefreshRateRange(refreshRateLow, refreshRateHigh);
- assertThat(vote.refreshRateRange).isEqualTo(expectedRange);
+ new RefreshRateRange(frameRateLow, frameRateHigh);
+ assertThat(vote.refreshRateRanges.render).isEqualTo(expectedRange);
}
public static class FakeDeviceConfig extends FakeDeviceConfigInterface {
@@ -2083,6 +2546,11 @@ public class DisplayModeDirectorTest {
return null;
}
+ @Override
+ public boolean renderFrameRateIsPhysicalRefreshRate() {
+ return true;
+ }
+
void notifyPeakRefreshRateChanged() {
if (mPeakRefreshRateObserver != null) {
mPeakRefreshRateObserver.dispatchChange(false /*selfChange*/,