Merge "Split refresh rate range into two ranges" into rvc-dev am: 5724666853

Change-Id: I3ab1225ff065704a3c560a487ff0a4e9781960d7
This commit is contained in:
Steven Thomas
2020-05-02 02:24:46 +00:00
committed by Automerger Merge Worker
6 changed files with 283 additions and 121 deletions

View File

@@ -1464,8 +1464,23 @@ public final class SurfaceControl implements Parcelable {
*/
public static final class DesiredDisplayConfigSpecs {
public int defaultConfig;
public float minRefreshRate;
public float maxRefreshRate;
/**
* 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.
*/
public float primaryRefreshRateMin;
public float primaryRefreshRateMax;
/**
* 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.
*/
public float appRequestRefreshRateMin;
public float appRequestRefreshRateMax;
public DesiredDisplayConfigSpecs() {}
@@ -1473,11 +1488,14 @@ public final class SurfaceControl implements Parcelable {
copyFrom(other);
}
public DesiredDisplayConfigSpecs(
int defaultConfig, float minRefreshRate, float maxRefreshRate) {
public DesiredDisplayConfigSpecs(int defaultConfig, float primaryRefreshRateMin,
float primaryRefreshRateMax, float appRequestRefreshRateMin,
float appRequestRefreshRateMax) {
this.defaultConfig = defaultConfig;
this.minRefreshRate = minRefreshRate;
this.maxRefreshRate = maxRefreshRate;
this.primaryRefreshRateMin = primaryRefreshRateMin;
this.primaryRefreshRateMax = primaryRefreshRateMax;
this.appRequestRefreshRateMin = appRequestRefreshRateMin;
this.appRequestRefreshRateMax = appRequestRefreshRateMax;
}
@Override
@@ -1490,8 +1508,10 @@ public final class SurfaceControl implements Parcelable {
*/
public boolean equals(DesiredDisplayConfigSpecs other) {
return other != null && defaultConfig == other.defaultConfig
&& minRefreshRate == other.minRefreshRate
&& maxRefreshRate == other.maxRefreshRate;
&& primaryRefreshRateMin == other.primaryRefreshRateMin
&& primaryRefreshRateMax == other.primaryRefreshRateMax
&& appRequestRefreshRateMin == other.appRequestRefreshRateMin
&& appRequestRefreshRateMax == other.appRequestRefreshRateMax;
}
@Override
@@ -1504,14 +1524,18 @@ public final class SurfaceControl implements Parcelable {
*/
public void copyFrom(DesiredDisplayConfigSpecs other) {
defaultConfig = other.defaultConfig;
minRefreshRate = other.minRefreshRate;
maxRefreshRate = other.maxRefreshRate;
primaryRefreshRateMin = other.primaryRefreshRateMin;
primaryRefreshRateMax = other.primaryRefreshRateMax;
appRequestRefreshRateMin = other.appRequestRefreshRateMin;
appRequestRefreshRateMax = other.appRequestRefreshRateMax;
}
@Override
public String toString() {
return String.format("defaultConfig=%d min=%.0f max=%.0f", defaultConfig,
minRefreshRate, maxRefreshRate);
return String.format("defaultConfig=%d primaryRefreshRateRange=[%.0f %.0f]"
+ " appRequestRefreshRateRange=[%.0f %.0f]",
defaultConfig, primaryRefreshRateMin, primaryRefreshRateMax,
appRequestRefreshRateMin, appRequestRefreshRateMax);
}
}

View File

@@ -174,8 +174,10 @@ static struct {
jclass clazz;
jmethodID ctor;
jfieldID defaultConfig;
jfieldID minRefreshRate;
jfieldID maxRefreshRate;
jfieldID primaryRefreshRateMin;
jfieldID primaryRefreshRateMax;
jfieldID appRequestRefreshRateMin;
jfieldID appRequestRefreshRateMax;
} gDesiredDisplayConfigSpecsClassInfo;
class JNamedColorSpace {
@@ -919,13 +921,24 @@ static jboolean nativeSetDesiredDisplayConfigSpecs(JNIEnv* env, jclass clazz, jo
jint defaultConfig = env->GetIntField(desiredDisplayConfigSpecs,
gDesiredDisplayConfigSpecsClassInfo.defaultConfig);
jfloat minRefreshRate = env->GetFloatField(desiredDisplayConfigSpecs,
gDesiredDisplayConfigSpecsClassInfo.minRefreshRate);
jfloat maxRefreshRate = env->GetFloatField(desiredDisplayConfigSpecs,
gDesiredDisplayConfigSpecsClassInfo.maxRefreshRate);
jfloat primaryRefreshRateMin =
env->GetFloatField(desiredDisplayConfigSpecs,
gDesiredDisplayConfigSpecsClassInfo.primaryRefreshRateMin);
jfloat primaryRefreshRateMax =
env->GetFloatField(desiredDisplayConfigSpecs,
gDesiredDisplayConfigSpecsClassInfo.primaryRefreshRateMax);
jfloat appRequestRefreshRateMin =
env->GetFloatField(desiredDisplayConfigSpecs,
gDesiredDisplayConfigSpecsClassInfo.appRequestRefreshRateMin);
jfloat appRequestRefreshRateMax =
env->GetFloatField(desiredDisplayConfigSpecs,
gDesiredDisplayConfigSpecsClassInfo.appRequestRefreshRateMax);
size_t result = SurfaceComposerClient::setDesiredDisplayConfigSpecs(
token, defaultConfig, minRefreshRate, maxRefreshRate);
size_t result = SurfaceComposerClient::setDesiredDisplayConfigSpecs(token, defaultConfig,
primaryRefreshRateMin,
primaryRefreshRateMax,
appRequestRefreshRateMin,
appRequestRefreshRateMax);
return result == NO_ERROR ? JNI_TRUE : JNI_FALSE;
}
@@ -934,16 +947,23 @@ static jobject nativeGetDesiredDisplayConfigSpecs(JNIEnv* env, jclass clazz, job
if (token == nullptr) return nullptr;
int32_t defaultConfig;
float minRefreshRate;
float maxRefreshRate;
if (SurfaceComposerClient::getDesiredDisplayConfigSpecs(token, &defaultConfig, &minRefreshRate,
&maxRefreshRate) != NO_ERROR) {
float primaryRefreshRateMin;
float primaryRefreshRateMax;
float appRequestRefreshRateMin;
float appRequestRefreshRateMax;
if (SurfaceComposerClient::getDesiredDisplayConfigSpecs(token, &defaultConfig,
&primaryRefreshRateMin,
&primaryRefreshRateMax,
&appRequestRefreshRateMin,
&appRequestRefreshRateMax) !=
NO_ERROR) {
return nullptr;
}
return env->NewObject(gDesiredDisplayConfigSpecsClassInfo.clazz,
gDesiredDisplayConfigSpecsClassInfo.ctor, defaultConfig, minRefreshRate,
maxRefreshRate);
gDesiredDisplayConfigSpecsClassInfo.ctor, defaultConfig,
primaryRefreshRateMin, primaryRefreshRateMax, appRequestRefreshRateMin,
appRequestRefreshRateMax);
}
static jint nativeGetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj) {
@@ -1757,13 +1777,17 @@ int register_android_view_SurfaceControl(JNIEnv* env)
gDesiredDisplayConfigSpecsClassInfo.clazz =
MakeGlobalRefOrDie(env, desiredDisplayConfigSpecsClazz);
gDesiredDisplayConfigSpecsClassInfo.ctor =
GetMethodIDOrDie(env, gDesiredDisplayConfigSpecsClassInfo.clazz, "<init>", "(IFF)V");
GetMethodIDOrDie(env, gDesiredDisplayConfigSpecsClassInfo.clazz, "<init>", "(IFFFF)V");
gDesiredDisplayConfigSpecsClassInfo.defaultConfig =
GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "defaultConfig", "I");
gDesiredDisplayConfigSpecsClassInfo.minRefreshRate =
GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "minRefreshRate", "F");
gDesiredDisplayConfigSpecsClassInfo.maxRefreshRate =
GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "maxRefreshRate", "F");
gDesiredDisplayConfigSpecsClassInfo.primaryRefreshRateMin =
GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "primaryRefreshRateMin", "F");
gDesiredDisplayConfigSpecsClassInfo.primaryRefreshRateMax =
GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "primaryRefreshRateMax", "F");
gDesiredDisplayConfigSpecsClassInfo.appRequestRefreshRateMin =
GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "appRequestRefreshRateMin", "F");
gDesiredDisplayConfigSpecsClassInfo.appRequestRefreshRateMax =
GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "appRequestRefreshRateMax", "F");
return err;
}

View File

@@ -152,6 +152,47 @@ public class DisplayModeDirector {
return votes;
}
private static final class VoteSummary {
public float minRefreshRate;
public float maxRefreshRate;
public int width;
public int height;
VoteSummary() {
reset();
}
public void reset() {
minRefreshRate = 0f;
maxRefreshRate = Float.POSITIVE_INFINITY;
width = Vote.INVALID_SIZE;
height = Vote.INVALID_SIZE;
}
}
// VoteSummary is returned as an output param to cut down a bit on the number of temporary
// objects.
private void summarizeVotes(
SparseArray<Vote> votes, int lowestConsideredPriority, /*out*/ VoteSummary summary) {
summary.reset();
for (int priority = Vote.MAX_PRIORITY; priority >= lowestConsideredPriority; priority--) {
Vote vote = votes.get(priority);
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 display size, use only the first vote we come across (i.e. the highest
// priority vote that includes the width / height).
if (summary.height == Vote.INVALID_SIZE && summary.width == Vote.INVALID_SIZE
&& vote.height > 0 && vote.width > 0) {
summary.width = vote.width;
summary.height = vote.height;
}
}
}
/**
* Calculates the refresh rate ranges and display modes that the system is allowed to freely
* switch between based on global and display-specific constraints.
@@ -174,52 +215,31 @@ public class DisplayModeDirector {
}
int[] availableModes = new int[]{defaultMode.getModeId()};
float minRefreshRate = 0f;
float maxRefreshRate = Float.POSITIVE_INFINITY;
VoteSummary primarySummary = new VoteSummary();
int lowestConsideredPriority = Vote.MIN_PRIORITY;
while (lowestConsideredPriority <= Vote.MAX_PRIORITY) {
minRefreshRate = 0f;
maxRefreshRate = Float.POSITIVE_INFINITY;
int height = Vote.INVALID_SIZE;
int width = Vote.INVALID_SIZE;
for (int priority = Vote.MAX_PRIORITY;
priority >= lowestConsideredPriority; priority--) {
Vote vote = votes.get(priority);
if (vote == null) {
continue;
}
// For refresh rates, just use the tightest bounds of all the votes
minRefreshRate = Math.max(minRefreshRate, vote.refreshRateRange.min);
maxRefreshRate = Math.min(maxRefreshRate, vote.refreshRateRange.max);
// For display size, use only the first vote we come across (i.e. the highest
// priority vote that includes the width / height).
if (height == Vote.INVALID_SIZE && width == Vote.INVALID_SIZE
&& vote.height > 0 && vote.width > 0) {
width = vote.width;
height = vote.height;
}
}
summarizeVotes(votes, lowestConsideredPriority, primarySummary);
// If we don't have anything specifying the width / height of the display, just use
// the default width and height. We don't want these switching out from underneath
// us since it's a pretty disruptive behavior.
if (height == Vote.INVALID_SIZE || width == Vote.INVALID_SIZE) {
width = defaultMode.getPhysicalWidth();
height = defaultMode.getPhysicalHeight();
if (primarySummary.height == Vote.INVALID_SIZE
|| primarySummary.width == Vote.INVALID_SIZE) {
primarySummary.width = defaultMode.getPhysicalWidth();
primarySummary.height = defaultMode.getPhysicalHeight();
}
availableModes = filterModes(modes, width, height, minRefreshRate, maxRefreshRate);
availableModes = filterModes(modes, primarySummary);
if (availableModes.length > 0) {
if (DEBUG) {
Slog.w(TAG, "Found available modes=" + Arrays.toString(availableModes)
+ " with lowest priority considered "
+ Vote.priorityToString(lowestConsideredPriority)
+ " and constraints: "
+ "width=" + width
+ ", height=" + height
+ ", minRefreshRate=" + minRefreshRate
+ ", maxRefreshRate=" + maxRefreshRate);
+ "width=" + primarySummary.width
+ ", height=" + primarySummary.height
+ ", minRefreshRate=" + primarySummary.minRefreshRate
+ ", maxRefreshRate=" + primarySummary.maxRefreshRate);
}
break;
}
@@ -228,10 +248,10 @@ public class DisplayModeDirector {
Slog.w(TAG, "Couldn't find available modes with lowest priority set to "
+ Vote.priorityToString(lowestConsideredPriority)
+ " and with the following constraints: "
+ "width=" + width
+ ", height=" + height
+ ", minRefreshRate=" + minRefreshRate
+ ", maxRefreshRate=" + maxRefreshRate);
+ "width=" + primarySummary.width
+ ", height=" + primarySummary.height
+ ", minRefreshRate=" + primarySummary.minRefreshRate
+ ", maxRefreshRate=" + primarySummary.maxRefreshRate);
}
// If we haven't found anything with the current set of votes, drop the
@@ -239,6 +259,20 @@ public class DisplayModeDirector {
lowestConsideredPriority++;
}
VoteSummary appRequestSummary = new VoteSummary();
summarizeVotes(
votes, Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, appRequestSummary);
appRequestSummary.minRefreshRate =
Math.min(appRequestSummary.minRefreshRate, primarySummary.minRefreshRate);
appRequestSummary.maxRefreshRate =
Math.max(appRequestSummary.maxRefreshRate, primarySummary.maxRefreshRate);
if (DEBUG) {
Slog.i(TAG,
String.format("App request range: [%.0f %.0f]",
appRequestSummary.minRefreshRate,
appRequestSummary.maxRefreshRate));
}
int baseModeId = defaultMode.getModeId();
if (availableModes.length > 0) {
baseModeId = availableModes[0];
@@ -246,20 +280,23 @@ public class DisplayModeDirector {
// filterModes function is going to filter the modes based on the voting system. If
// the application requests a given mode with preferredModeId function, it will be
// stored as baseModeId.
return new DesiredDisplayModeSpecs(
baseModeId, new RefreshRateRange(minRefreshRate, maxRefreshRate));
return new DesiredDisplayModeSpecs(baseModeId,
new RefreshRateRange(
primarySummary.minRefreshRate, primarySummary.maxRefreshRate),
new RefreshRateRange(
appRequestSummary.minRefreshRate, appRequestSummary.maxRefreshRate));
}
}
private int[] filterModes(Display.Mode[] supportedModes,
int width, int height, float minRefreshRate, float maxRefreshRate) {
private int[] filterModes(Display.Mode[] supportedModes, VoteSummary summary) {
ArrayList<Display.Mode> availableModes = new ArrayList<>();
for (Display.Mode mode : supportedModes) {
if (mode.getPhysicalWidth() != width || mode.getPhysicalHeight() != height) {
if (mode.getPhysicalWidth() != summary.width
|| mode.getPhysicalHeight() != summary.height) {
if (DEBUG) {
Slog.w(TAG, "Discarding mode " + mode.getModeId() + ", wrong size"
+ ": desiredWidth=" + width
+ ": desiredHeight=" + height
+ ": desiredWidth=" + summary.width
+ ": desiredHeight=" + summary.height
+ ": actualWidth=" + mode.getPhysicalWidth()
+ ": actualHeight=" + mode.getPhysicalHeight());
}
@@ -269,13 +306,13 @@ public class DisplayModeDirector {
// 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 < (minRefreshRate - FLOAT_TOLERANCE)
|| refreshRate > (maxRefreshRate + FLOAT_TOLERANCE)) {
if (refreshRate < (summary.minRefreshRate - FLOAT_TOLERANCE)
|| refreshRate > (summary.maxRefreshRate + FLOAT_TOLERANCE)) {
if (DEBUG) {
Slog.w(TAG, "Discarding mode " + mode.getModeId()
+ ", outside refresh rate bounds"
+ ": minRefreshRate=" + minRefreshRate
+ ", maxRefreshRate=" + maxRefreshRate
+ ": minRefreshRate=" + summary.minRefreshRate
+ ", maxRefreshRate=" + summary.maxRefreshRate
+ ", modeRefreshRate=" + refreshRate);
}
continue;
@@ -535,7 +572,7 @@ public class DisplayModeDirector {
/**
* Information about the desired display mode to be set by the system. Includes the base
* mode ID and refresh rate range.
* mode ID and the primary and app request refresh rate ranges.
*
* We have this class in addition to SurfaceControl.DesiredDisplayConfigSpecs to make clear the
* distinction between the config ID / physical index that
@@ -548,17 +585,28 @@ public class DisplayModeDirector {
*/
public int baseModeId;
/**
* The refresh rate range.
* The primary refresh rate range.
*/
public final RefreshRateRange refreshRateRange;
public final RefreshRateRange primaryRefreshRateRange;
/**
* The app request refresh rate range. Lower priority considerations won't be included in
* this range, allowing surface flinger 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 DesiredDisplayModeSpecs() {
refreshRateRange = new RefreshRateRange();
primaryRefreshRateRange = new RefreshRateRange();
appRequestRefreshRateRange = new RefreshRateRange();
}
public DesiredDisplayModeSpecs(int baseModeId, @NonNull RefreshRateRange refreshRateRange) {
public DesiredDisplayModeSpecs(int baseModeId,
@NonNull RefreshRateRange primaryRefreshRateRange,
@NonNull RefreshRateRange appRequestRefreshRateRange) {
this.baseModeId = baseModeId;
this.refreshRateRange = refreshRateRange;
this.primaryRefreshRateRange = primaryRefreshRateRange;
this.appRequestRefreshRateRange = appRequestRefreshRateRange;
}
/**
@@ -566,8 +614,10 @@ public class DisplayModeDirector {
*/
@Override
public String toString() {
return String.format("baseModeId=%d min=%.0f max=%.0f", baseModeId,
refreshRateRange.min, refreshRateRange.max);
return String.format("baseModeId=%d primaryRefreshRateRange=[%.0f %.0f]"
+ " appRequestRefreshRateRange=[%.0f %.0f]",
baseModeId, primaryRefreshRateRange.min, primaryRefreshRateRange.max,
appRequestRefreshRateRange.min, appRequestRefreshRateRange.max);
}
/**
* Checks whether the two objects have the same values.
@@ -587,7 +637,11 @@ public class DisplayModeDirector {
if (baseModeId != desiredDisplayModeSpecs.baseModeId) {
return false;
}
if (!refreshRateRange.equals(desiredDisplayModeSpecs.refreshRateRange)) {
if (!primaryRefreshRateRange.equals(desiredDisplayModeSpecs.primaryRefreshRateRange)) {
return false;
}
if (!appRequestRefreshRateRange.equals(
desiredDisplayModeSpecs.appRequestRefreshRateRange)) {
return false;
}
return true;
@@ -595,7 +649,7 @@ public class DisplayModeDirector {
@Override
public int hashCode() {
return Objects.hash(baseModeId, refreshRateRange);
return Objects.hash(baseModeId, primaryRefreshRateRange, appRequestRefreshRateRange);
}
/**
@@ -603,8 +657,10 @@ public class DisplayModeDirector {
*/
public void copyFrom(DesiredDisplayModeSpecs other) {
baseModeId = other.baseModeId;
refreshRateRange.min = other.refreshRateRange.min;
refreshRateRange.max = other.refreshRateRange.max;
primaryRefreshRateRange.min = other.primaryRefreshRateRange.min;
primaryRefreshRateRange.max = other.primaryRefreshRateRange.max;
appRequestRefreshRateRange.min = other.appRequestRefreshRateRange.min;
appRequestRefreshRateRange.max = other.appRequestRefreshRateRange.max;
}
}
@@ -637,12 +693,17 @@ public class DisplayModeDirector {
// LOW_POWER_MODE force display to [0, 60HZ] if Settings.Global.LOW_POWER_MODE is on.
public static final int PRIORITY_LOW_POWER_MODE = 5;
// Whenever a new priority is added, remember to update MIN_PRIORITY and/or MAX_PRIORITY as
// appropriate, as well as priorityToString.
// 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_LOW_BRIGHTNESS;
public static final int MAX_PRIORITY = PRIORITY_LOW_POWER_MODE;
// 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;
/**
* A value signifying an invalid width or height in a vote.
*/

View File

@@ -310,9 +310,14 @@ final class LocalDisplayAdapter extends DisplayAdapter {
// list of available modes will take care of updating display config specs.
if (activeBaseMode != NO_DISPLAY_MODE_ID) {
if (mDisplayModeSpecs.baseModeId != activeBaseMode
|| mDisplayModeSpecs.refreshRateRange.min != configSpecs.minRefreshRate
|| mDisplayModeSpecs.refreshRateRange.max
!= configSpecs.maxRefreshRate) {
|| mDisplayModeSpecs.primaryRefreshRateRange.min
!= configSpecs.primaryRefreshRateMin
|| mDisplayModeSpecs.primaryRefreshRateRange.max
!= configSpecs.primaryRefreshRateMax
|| mDisplayModeSpecs.appRequestRefreshRateRange.min
!= configSpecs.appRequestRefreshRateMin
|| mDisplayModeSpecs.appRequestRefreshRateRange.max
!= configSpecs.appRequestRefreshRateMax) {
mDisplayModeSpecsInvalid = true;
sendTraversalRequestLocked();
}
@@ -799,8 +804,10 @@ final class LocalDisplayAdapter extends DisplayAdapter {
LocalDisplayDevice::setDesiredDisplayModeSpecsAsync, this,
getDisplayTokenLocked(),
new SurfaceControl.DesiredDisplayConfigSpecs(baseConfigId,
mDisplayModeSpecs.refreshRateRange.min,
mDisplayModeSpecs.refreshRateRange.max)));
mDisplayModeSpecs.primaryRefreshRateRange.min,
mDisplayModeSpecs.primaryRefreshRateRange.max,
mDisplayModeSpecs.appRequestRefreshRateRange.min,
mDisplayModeSpecs.appRequestRefreshRateRange.max)));
}
}

View File

@@ -308,7 +308,7 @@ public class LocalDisplayAdapterTest {
doReturn(0).when(() -> SurfaceControl.getActiveColorMode(display.token));
doReturn(new int[] { 0 }).when(
() -> SurfaceControl.getDisplayColorModes(display.token));
doReturn(new SurfaceControl.DesiredDisplayConfigSpecs(0, 60.f, 60.f))
doReturn(new SurfaceControl.DesiredDisplayConfigSpecs(0, 60.f, 60.f, 60.f, 60.f))
.when(() -> SurfaceControl.getDesiredDisplayConfigSpecs(display.token));
}

View File

@@ -16,7 +16,6 @@
package com.android.server.display;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import android.content.Context;
@@ -30,7 +29,6 @@ import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.server.display.DisplayModeDirector.DesiredDisplayModeSpecs;
import com.android.server.display.DisplayModeDirector.RefreshRateRange;
import com.android.server.display.DisplayModeDirector.Vote;
import com.google.common.truth.Truth;
@@ -79,10 +77,12 @@ public class DisplayModeDirectorTest {
int displayId = 0;
// With no votes present, DisplayModeDirector should allow any refresh rate.
assertEquals(new DesiredDisplayModeSpecs(/*baseModeId=*/60,
new RefreshRateRange(0f, Float.POSITIVE_INFINITY)),
DesiredDisplayModeSpecs modeSpecs =
createDisplayModeDirectorWithDisplayFpsRange(60, 90).getDesiredDisplayModeSpecs(
displayId));
displayId);
Truth.assertThat(modeSpecs.baseModeId).isEqualTo(60);
Truth.assertThat(modeSpecs.primaryRefreshRateRange.min).isEqualTo(0f);
Truth.assertThat(modeSpecs.primaryRefreshRateRange.max).isEqualTo(Float.POSITIVE_INFINITY);
int numPriorities =
DisplayModeDirector.Vote.MAX_PRIORITY - DisplayModeDirector.Vote.MIN_PRIORITY + 1;
@@ -101,10 +101,12 @@ public class DisplayModeDirectorTest {
int priority = Vote.MIN_PRIORITY + i;
votes.put(priority, Vote.forRefreshRates(minFps + i, maxFps - i));
director.injectVotesByDisplay(votesByDisplay);
assertEquals(new DesiredDisplayModeSpecs(
/*baseModeId=*/minFps + i,
new RefreshRateRange(minFps + i, maxFps - i)),
director.getDesiredDisplayModeSpecs(displayId));
modeSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(modeSpecs.baseModeId).isEqualTo(minFps + i);
Truth.assertThat(modeSpecs.primaryRefreshRateRange.min)
.isEqualTo((float) (minFps + i));
Truth.assertThat(modeSpecs.primaryRefreshRateRange.max)
.isEqualTo((float) (maxFps - i));
}
}
@@ -119,9 +121,10 @@ public class DisplayModeDirectorTest {
votes.put(Vote.MAX_PRIORITY, Vote.forRefreshRates(65, 85));
votes.put(Vote.MIN_PRIORITY, Vote.forRefreshRates(70, 80));
director.injectVotesByDisplay(votesByDisplay);
assertEquals(new DesiredDisplayModeSpecs(/*baseModeId=*/70,
new RefreshRateRange(70, 80)),
director.getDesiredDisplayModeSpecs(displayId));
modeSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(modeSpecs.baseModeId).isEqualTo(70);
Truth.assertThat(modeSpecs.primaryRefreshRateRange.min).isEqualTo(70f);
Truth.assertThat(modeSpecs.primaryRefreshRateRange.max).isEqualTo(80f);
}
}
@@ -140,8 +143,8 @@ public class DisplayModeDirectorTest {
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(desiredSpecs.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
Truth.assertThat(desiredSpecs.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
Truth.assertThat(desiredSpecs.baseModeId).isEqualTo(60);
}
@@ -159,34 +162,77 @@ public class DisplayModeDirectorTest {
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(desiredSpecs.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
Truth.assertThat(desiredSpecs.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 90));
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(90, 90));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(desiredSpecs.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
Truth.assertThat(desiredSpecs.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(90, 90));
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(desiredSpecs.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
Truth.assertThat(desiredSpecs.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 60));
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(90, 90));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(desiredSpecs.refreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
Truth.assertThat(desiredSpecs.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
}
@Test
public void testAppRequestRefreshRateRange() {
// Confirm that the app request range doesn't include low brightness or min refresh rate
// settings, but does include everything else.
assertTrue(
Vote.PRIORITY_LOW_BRIGHTNESS < Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
assertTrue(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE
< Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
assertTrue(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE
>= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
int displayId = 0;
DisplayModeDirector director = createDisplayModeDirectorWithDisplayFpsRange(60, 90);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(displayId, votes);
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60));
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.min).isAtMost(60f);
Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f);
votes.put(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE,
Vote.forRefreshRates(90, Float.POSITIVE_INFINITY));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isAtLeast(90f);
Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.min).isAtMost(60f);
Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f);
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(75, 75));
director.injectVotesByDisplay(votesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(75);
Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(75);
Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.min)
.isWithin(FLOAT_TOLERANCE)
.of(75);
Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.max)
.isWithin(FLOAT_TOLERANCE)
.of(75);
}
}