summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Oleg Petšjonkin <petsjonkin@google.com> 2024-06-03 11:25:50 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2024-06-03 11:25:50 +0000
commit9e8915c6a0abcfd8de38537c1e8507bc585e47da (patch)
treea42f47e7c341bc901ce463d16e03616a9873989d
parentdb708ebb8f1748bc6004bc9396a11ec7f3499a4e (diff)
parente5339e5cf80ec05154bbfe36ec3f04979319377d (diff)
Merge "Intoroducing RequestedRefreshRateVote" into main
-rw-r--r--core/java/android/view/Display.java1
-rw-r--r--core/java/android/view/DisplayInfo.java2
-rw-r--r--services/core/java/com/android/server/display/DisplayAdapter.java2
-rw-r--r--services/core/java/com/android/server/display/feature/DisplayManagerFlags.java2
-rw-r--r--services/core/java/com/android/server/display/mode/DisplayModeDirector.java156
-rw-r--r--services/core/java/com/android/server/display/mode/RequestedRefreshRateVote.java51
-rw-r--r--services/core/java/com/android/server/display/mode/SyntheticModeManager.java6
-rw-r--r--services/core/java/com/android/server/display/mode/Vote.java4
-rw-r--r--services/core/java/com/android/server/display/mode/VoteSummary.java26
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/mode/AppRequestObserverTest.kt6
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/mode/RequestedRefreshRateVoteTest.kt58
-rw-r--r--services/tests/displayservicetests/src/com/android/server/display/mode/VoteSummaryTest.kt40
12 files changed, 249 insertions, 105 deletions
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index ba1915c77060..15b0c13de524 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -2263,6 +2263,7 @@ public final class Display {
this(modeId, width, height, refreshRate, vsyncRate, false, alternativeRefreshRates,
supportedHdrTypes);
}
+
/**
* @hide
*/
diff --git a/core/java/android/view/DisplayInfo.java b/core/java/android/view/DisplayInfo.java
index da86e2dc2383..8b9d876f6bf1 100644
--- a/core/java/android/view/DisplayInfo.java
+++ b/core/java/android/view/DisplayInfo.java
@@ -213,7 +213,7 @@ public final class DisplayInfo implements Parcelable {
/**
* The supported modes that will be exposed externally.
- * Might have different set of modes that supportedModes for VRR displays
+ * Might have different set of modes than supportedModes for VRR displays
*/
public Display.Mode[] appsSupportedModes = Display.Mode.EMPTY_ARRAY;
diff --git a/services/core/java/com/android/server/display/DisplayAdapter.java b/services/core/java/com/android/server/display/DisplayAdapter.java
index 5690a9e6ec89..69bc66fea56c 100644
--- a/services/core/java/com/android/server/display/DisplayAdapter.java
+++ b/services/core/java/com/android/server/display/DisplayAdapter.java
@@ -135,7 +135,7 @@ abstract class DisplayAdapter {
float[] alternativeRefreshRates,
@Display.HdrCapabilities.HdrType int[] supportedHdrTypes) {
return new Display.Mode(NEXT_DISPLAY_MODE_ID.getAndIncrement(), width, height, refreshRate,
- vsyncRate, false, alternativeRefreshRates, supportedHdrTypes);
+ vsyncRate, /* isSynthetic= */ false, alternativeRefreshRates, supportedHdrTypes);
}
public interface Listener {
diff --git a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
index f923cbc978ff..f56d8036f870 100644
--- a/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
+++ b/services/core/java/com/android/server/display/feature/DisplayManagerFlags.java
@@ -353,7 +353,7 @@ public class DisplayManagerFlags {
}
/**
- * @return Whether to ignore preferredRefreshRate app request or not
+ * @return Whether to ignore preferredRefreshRate app request conversion to display mode or not
*/
public boolean ignoreAppPreferredRefreshRateRequest() {
return mIgnoreAppPreferredRefreshRate.isEnabled();
diff --git a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
index 76a2827050a9..d519748929bf 100644
--- a/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/mode/DisplayModeDirector.java
@@ -1254,13 +1254,9 @@ public class DisplayModeDirector {
* Responsible for keeping track of app requested refresh rates per display
*/
public final class AppRequestObserver {
- private final SparseArray<Display.Mode> mAppRequestedModeByDisplay;
- private final SparseArray<RefreshRateRange> mAppPreferredRefreshRateRangeByDisplay;
private final boolean mIgnorePreferredRefreshRate;
AppRequestObserver(DisplayManagerFlags flags) {
- mAppRequestedModeByDisplay = new SparseArray<>();
- mAppPreferredRefreshRateRangeByDisplay = new SparseArray<>();
mIgnorePreferredRefreshRate = flags.ignoreAppPreferredRefreshRateRequest();
}
@@ -1269,104 +1265,84 @@ public class DisplayModeDirector {
*/
public void setAppRequest(int displayId, int modeId, float requestedRefreshRate,
float requestedMinRefreshRateRange, float requestedMaxRefreshRateRange) {
+ Display.Mode requestedMode;
+ synchronized (mLock) {
+ requestedMode = findModeLocked(displayId, modeId, requestedRefreshRate);
+ }
- if (modeId == 0 && requestedRefreshRate != 0 && !mIgnorePreferredRefreshRate) {
+ Vote frameRateVote = getFrameRateVote(
+ requestedMinRefreshRateRange, requestedMaxRefreshRateRange);
+ Vote baseModeRefreshRateVote = getBaseModeVote(requestedMode, requestedRefreshRate);
+ Vote sizeVote = getSizeVote(requestedMode);
+
+ mVotesStorage.updateVote(displayId, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE,
+ frameRateVote);
+ mVotesStorage.updateVote(displayId, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
+ baseModeRefreshRateVote);
+ mVotesStorage.updateVote(displayId, Vote.PRIORITY_APP_REQUEST_SIZE, sizeVote);
+ }
+
+ private Display.Mode findModeLocked(int displayId, int modeId, float requestedRefreshRate) {
+ Display.Mode mode = null;
+ if (modeId != 0) {
+ mode = findAppModeByIdLocked(displayId, modeId);
+ } else if (requestedRefreshRate != 0 && !mIgnorePreferredRefreshRate) { // modeId == 0
// Scan supported modes returned to find a mode with the same
// size as the default display mode but with the specified refresh rate instead.
- Display.Mode mode = findDefaultModeByRefreshRate(displayId, requestedRefreshRate);
- if (mode != null) {
- modeId = mode.getModeId();
- } else {
+ mode = findDefaultModeByRefreshRateLocked(displayId, requestedRefreshRate);
+ if (mode == null) {
Slog.e(TAG, "Couldn't find a mode for the requestedRefreshRate: "
+ requestedRefreshRate + " on Display: " + displayId);
}
}
-
- synchronized (mLock) {
- setAppRequestedModeLocked(displayId, modeId);
- setAppPreferredRefreshRateRangeLocked(displayId, requestedMinRefreshRateRange,
- requestedMaxRefreshRateRange);
- }
+ return mode;
}
- @Nullable
- private Display.Mode findDefaultModeByRefreshRate(int displayId, float refreshRate) {
- Display.Mode[] modes;
- Display.Mode defaultMode;
- synchronized (mLock) {
- modes = mAppSupportedModesByDisplay.get(displayId);
- defaultMode = mDefaultModeByDisplay.get(displayId);
- }
- for (int i = 0; i < modes.length; i++) {
- if (modes[i].matches(defaultMode.getPhysicalWidth(),
- defaultMode.getPhysicalHeight(), refreshRate)) {
- return modes[i];
+ private Vote getFrameRateVote(float minRefreshRate, float maxRefreshRate) {
+ RefreshRateRange refreshRateRange = null;
+ if (minRefreshRate > 0 || maxRefreshRate > 0) {
+ float max = maxRefreshRate > 0
+ ? maxRefreshRate : Float.POSITIVE_INFINITY;
+ refreshRateRange = new RefreshRateRange(minRefreshRate, max);
+ if (refreshRateRange.min == 0 && refreshRateRange.max == 0) {
+ // minRefreshRate/maxRefreshRate were invalid
+ refreshRateRange = null;
}
}
- return null;
+ return refreshRateRange != null
+ ? Vote.forRenderFrameRates(refreshRateRange.min, refreshRateRange.max) : null;
}
- private void setAppRequestedModeLocked(int displayId, int modeId) {
- final Display.Mode requestedMode = findAppModeByIdLocked(displayId, modeId);
- if (Objects.equals(requestedMode, mAppRequestedModeByDisplay.get(displayId))) {
- return;
- }
- final Vote baseModeRefreshRateVote;
- final Vote sizeVote;
- if (requestedMode != null) {
- mAppRequestedModeByDisplay.put(displayId, requestedMode);
- sizeVote = Vote.forSize(requestedMode.getPhysicalWidth(),
- requestedMode.getPhysicalHeight());
- if (requestedMode.isSynthetic()) {
- // TODO: for synthetic mode we should not limit frame rate, we must ensure
- // that frame rate is reachable within other Votes constraints
- baseModeRefreshRateVote = Vote.forRenderFrameRates(
- requestedMode.getRefreshRate(), requestedMode.getRefreshRate());
+ private Vote getSizeVote(@Nullable Display.Mode mode) {
+ return mode != null
+ ? Vote.forSize(mode.getPhysicalWidth(), mode.getPhysicalHeight()) : null;
+ }
+
+ private Vote getBaseModeVote(@Nullable Display.Mode mode, float requestedRefreshRate) {
+ Vote vote = null;
+ if (mode != null) {
+ if (mode.isSynthetic()) {
+ vote = Vote.forRequestedRefreshRate(mode.getRefreshRate());
} else {
- baseModeRefreshRateVote =
- Vote.forBaseModeRefreshRate(requestedMode.getRefreshRate());
+ vote = Vote.forBaseModeRefreshRate(mode.getRefreshRate());
}
- } else {
- mAppRequestedModeByDisplay.remove(displayId);
- baseModeRefreshRateVote = null;
- sizeVote = null;
- }
-
- mVotesStorage.updateVote(displayId, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
- baseModeRefreshRateVote);
- mVotesStorage.updateVote(displayId, Vote.PRIORITY_APP_REQUEST_SIZE, sizeVote);
+ } else if (requestedRefreshRate != 0f && mIgnorePreferredRefreshRate) {
+ vote = Vote.forRequestedRefreshRate(requestedRefreshRate);
+ } // !mIgnorePreferredRefreshRate case is handled by findModeLocked
+ return vote;
}
- private void setAppPreferredRefreshRateRangeLocked(int displayId,
- float requestedMinRefreshRateRange, float requestedMaxRefreshRateRange) {
- final Vote vote;
-
- RefreshRateRange refreshRateRange = null;
- if (requestedMinRefreshRateRange > 0 || requestedMaxRefreshRateRange > 0) {
- float min = requestedMinRefreshRateRange;
- float max = requestedMaxRefreshRateRange > 0
- ? requestedMaxRefreshRateRange : Float.POSITIVE_INFINITY;
- refreshRateRange = new RefreshRateRange(min, max);
- if (refreshRateRange.min == 0 && refreshRateRange.max == 0) {
- // requestedMinRefreshRateRange/requestedMaxRefreshRateRange were invalid
- refreshRateRange = null;
+ @Nullable
+ private Display.Mode findDefaultModeByRefreshRateLocked(int displayId, float refreshRate) {
+ Display.Mode[] modes = mAppSupportedModesByDisplay.get(displayId);
+ Display.Mode defaultMode = mDefaultModeByDisplay.get(displayId);
+ for (int i = 0; i < modes.length; i++) {
+ if (modes[i].matches(defaultMode.getPhysicalWidth(),
+ defaultMode.getPhysicalHeight(), refreshRate)) {
+ return modes[i];
}
}
-
- if (Objects.equals(refreshRateRange,
- mAppPreferredRefreshRateRangeByDisplay.get(displayId))) {
- return;
- }
-
- if (refreshRateRange != null) {
- mAppPreferredRefreshRateRangeByDisplay.put(displayId, refreshRateRange);
- vote = Vote.forRenderFrameRates(refreshRateRange.min, refreshRateRange.max);
- } else {
- mAppPreferredRefreshRateRangeByDisplay.remove(displayId);
- vote = null;
- }
- mVotesStorage.updateVote(displayId, Vote.PRIORITY_APP_REQUEST_RENDER_FRAME_RATE_RANGE,
- vote);
+ return null;
}
private Display.Mode findAppModeByIdLocked(int displayId, int modeId) {
@@ -1384,19 +1360,7 @@ public class DisplayModeDirector {
private void dumpLocked(PrintWriter pw) {
pw.println(" AppRequestObserver");
- pw.println(" mAppRequestedModeByDisplay:");
- for (int i = 0; i < mAppRequestedModeByDisplay.size(); i++) {
- final int id = mAppRequestedModeByDisplay.keyAt(i);
- final Display.Mode mode = mAppRequestedModeByDisplay.valueAt(i);
- pw.println(" " + id + " -> " + mode);
- }
- pw.println(" mAppPreferredRefreshRateRangeByDisplay:");
- for (int i = 0; i < mAppPreferredRefreshRateRangeByDisplay.size(); i++) {
- final int id = mAppPreferredRefreshRateRangeByDisplay.keyAt(i);
- final RefreshRateRange refreshRateRange =
- mAppPreferredRefreshRateRangeByDisplay.valueAt(i);
- pw.println(" " + id + " -> " + refreshRateRange);
- }
+ pw.println(" mIgnorePreferredRefreshRate: " + mIgnorePreferredRefreshRate);
}
}
diff --git a/services/core/java/com/android/server/display/mode/RequestedRefreshRateVote.java b/services/core/java/com/android/server/display/mode/RequestedRefreshRateVote.java
new file mode 100644
index 000000000000..843cf8889a74
--- /dev/null
+++ b/services/core/java/com/android/server/display/mode/RequestedRefreshRateVote.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.mode;
+
+import android.annotation.NonNull;
+
+import java.util.Objects;
+
+class RequestedRefreshRateVote implements Vote {
+ final float mRefreshRate;
+
+ RequestedRefreshRateVote(float refreshRate) {
+ this.mRefreshRate = refreshRate;
+ }
+
+ @Override
+ public void updateSummary(@NonNull VoteSummary summary) {
+ summary.requestedRefreshRates.add(mRefreshRate);
+ }
+
+ @Override
+ public String toString() {
+ return "RequestedRefreshRateVote{ refreshRate=" + mRefreshRate + " }";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof RequestedRefreshRateVote that)) return false;
+ return Float.compare(mRefreshRate, that.mRefreshRate) == 0;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mRefreshRate);
+ }
+}
diff --git a/services/core/java/com/android/server/display/mode/SyntheticModeManager.java b/services/core/java/com/android/server/display/mode/SyntheticModeManager.java
index 5b6bbc512a42..a83b9395dfc0 100644
--- a/services/core/java/com/android/server/display/mode/SyntheticModeManager.java
+++ b/services/core/java/com/android/server/display/mode/SyntheticModeManager.java
@@ -32,7 +32,9 @@ import java.util.Map;
*/
public class SyntheticModeManager {
private static final float FLOAT_TOLERANCE = 0.01f;
- private static final float SYNTHETIC_MODE_HIGH_BOUNDARY = 60f + FLOAT_TOLERANCE;
+ private static final float SYNTHETIC_MODE_REFRESH_RATE = 60f;
+ private static final float SYNTHETIC_MODE_HIGH_BOUNDARY =
+ SYNTHETIC_MODE_REFRESH_RATE + FLOAT_TOLERANCE;
private final boolean mSynthetic60HzModesEnabled;
@@ -62,7 +64,7 @@ public class SyntheticModeManager {
nextModeId = mode.getModeId();
}
- float divisor = mode.getVsyncRate() / 60f;
+ float divisor = mode.getVsyncRate() / SYNTHETIC_MODE_REFRESH_RATE;
boolean is60HzAchievable = Math.abs(divisor - Math.round(divisor)) < FLOAT_TOLERANCE;
if (is60HzAchievable) {
sizes.put(new Size(mode.getPhysicalWidth(), mode.getPhysicalHeight()),
diff --git a/services/core/java/com/android/server/display/mode/Vote.java b/services/core/java/com/android/server/display/mode/Vote.java
index 3e8b3c5ec7ca..1ec469c21f7b 100644
--- a/services/core/java/com/android/server/display/mode/Vote.java
+++ b/services/core/java/com/android/server/display/mode/Vote.java
@@ -186,6 +186,10 @@ interface Vote {
return new BaseModeRefreshRateVote(baseModeRefreshRate);
}
+ static Vote forRequestedRefreshRate(float refreshRate) {
+ return new RequestedRefreshRateVote(refreshRate);
+ }
+
static Vote forSupportedRefreshRates(List<SupportedModeData> supportedModes) {
if (supportedModes.isEmpty()) {
return null;
diff --git a/services/core/java/com/android/server/display/mode/VoteSummary.java b/services/core/java/com/android/server/display/mode/VoteSummary.java
index d4ce892eeba9..00a922630d8e 100644
--- a/services/core/java/com/android/server/display/mode/VoteSummary.java
+++ b/services/core/java/com/android/server/display/mode/VoteSummary.java
@@ -23,7 +23,9 @@ import android.view.Display;
import android.view.SurfaceControl;
import java.util.ArrayList;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
final class VoteSummary {
private static final float FLOAT_TOLERANCE = SurfaceControl.RefreshRateRange.FLOAT_TOLERANCE;
@@ -38,7 +40,14 @@ final class VoteSummary {
public int minWidth;
public int minHeight;
public boolean disableRefreshRateSwitching;
+ /**
+ * available modes should have mode with specific refresh rate
+ */
public float appRequestBaseModeRefreshRate;
+ /**
+ * requestRefreshRate should be within [minRenderFrameRate, maxRenderFrameRate] range
+ */
+ public Set<Float> requestedRefreshRates = new HashSet<>();
@Nullable
public List<SupportedRefreshRatesVote.RefreshRates> supportedRefreshRates;
@@ -329,6 +338,21 @@ final class VoteSummary {
}
return false;
}
+
+ for (Float requestedRefreshRate : requestedRefreshRates) {
+ if (requestedRefreshRate < minRenderFrameRate
+ || requestedRefreshRate > maxRenderFrameRate) {
+ if (mLoggingEnabled) {
+ Slog.w(TAG, "Requested refreshRate is outside frame rate range"
+ + ": requestedRefreshRates=" + requestedRefreshRates
+ + ", requestedRefreshRate=" + requestedRefreshRate
+ + ", minRenderFrameRate=" + minRenderFrameRate
+ + ", maxRenderFrameRate=" + maxRenderFrameRate);
+ }
+ return false;
+ }
+ }
+
return true;
}
@@ -370,6 +394,7 @@ final class VoteSummary {
minHeight = 0;
disableRefreshRateSwitching = false;
appRequestBaseModeRefreshRate = 0f;
+ requestedRefreshRates.clear();
supportedRefreshRates = null;
supportedModeIds = null;
if (mLoggingEnabled) {
@@ -393,6 +418,7 @@ final class VoteSummary {
+ ", minHeight=" + minHeight
+ ", disableRefreshRateSwitching=" + disableRefreshRateSwitching
+ ", appRequestBaseModeRefreshRate=" + appRequestBaseModeRefreshRate
+ + ", requestRefreshRates=" + requestedRefreshRates
+ ", supportedRefreshRates=" + supportedRefreshRates
+ ", supportedModeIds=" + supportedModeIds
+ ", mIsDisplayResolutionRangeVotingEnabled="
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/AppRequestObserverTest.kt b/services/tests/displayservicetests/src/com/android/server/display/mode/AppRequestObserverTest.kt
index cf6146f2f35e..34c6ba90a0ba 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/AppRequestObserverTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/AppRequestObserverTest.kt
@@ -117,11 +117,11 @@ class AppRequestObserverTest {
BaseModeRefreshRateVote(60f), SizeVote(1000, 1000, 1000, 1000), RenderVote(60f, 90f)),
PREFERRED_REFRESH_RATE(false, 0, 60f, 0f, 0f,
BaseModeRefreshRateVote(60f), SizeVote(1000, 1000, 1000, 1000), null),
- PREFERRED_REFRESH_RATE_IGNORED(true, 0, 60f, 0f, 0f,
- null, null, null),
+ PREFERRED_REFRESH_RATE_IGNORE_BASE_MODE_CONVERSION(true, 0, 60f, 0f, 0f,
+ RequestedRefreshRateVote(60f), null, null),
PREFERRED_REFRESH_RATE_INVALID(false, 0, 25f, 0f, 0f,
null, null, null),
SYNTHETIC_MODE(false, 99, 0f, 0f, 0f,
- RenderVote(45f, 45f), SizeVote(1000, 1000, 1000, 1000), null),
+ RequestedRefreshRateVote(45f), SizeVote(1000, 1000, 1000, 1000), null),
}
} \ No newline at end of file
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/RequestedRefreshRateVoteTest.kt b/services/tests/displayservicetests/src/com/android/server/display/mode/RequestedRefreshRateVoteTest.kt
new file mode 100644
index 000000000000..dbe9e4ae5ef5
--- /dev/null
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/RequestedRefreshRateVoteTest.kt
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.display.mode
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class RequestedRefreshRateVoteTest {
+
+ @Test
+ fun `updates requestedRefreshRates`() {
+ val refreshRate = 90f
+ val vote = RequestedRefreshRateVote(refreshRate)
+ val summary = createVotesSummary()
+
+ vote.updateSummary(summary)
+
+ assertThat(summary.requestedRefreshRates).hasSize(1)
+ assertThat(summary.requestedRefreshRates).contains(refreshRate)
+ }
+
+ @Test
+ fun `updates requestedRefreshRates with multiple refresh rates`() {
+ val refreshRate1 = 90f
+ val vote1 = RequestedRefreshRateVote(refreshRate1)
+
+ val refreshRate2 = 60f
+ val vote2 = RequestedRefreshRateVote(refreshRate2)
+
+ val summary = createVotesSummary()
+
+ vote1.updateSummary(summary)
+ vote2.updateSummary(summary)
+
+ assertThat(summary.requestedRefreshRates).hasSize(2)
+ assertThat(summary.requestedRefreshRates).containsExactly(refreshRate1, refreshRate2)
+ }
+} \ No newline at end of file
diff --git a/services/tests/displayservicetests/src/com/android/server/display/mode/VoteSummaryTest.kt b/services/tests/displayservicetests/src/com/android/server/display/mode/VoteSummaryTest.kt
index 5da1bb63548b..dd5e1be8462c 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/mode/VoteSummaryTest.kt
+++ b/services/tests/displayservicetests/src/com/android/server/display/mode/VoteSummaryTest.kt
@@ -152,13 +152,51 @@ class VoteSummaryTest {
assertThat(result.map { it.modeId }).containsExactlyElementsIn(testCase.expectedModeIds)
}
+
+ @Test
+ fun `summary invalid if has requestedRefreshRate less than minRenederRate`() {
+ val summary = createSummary()
+ summary.requestedRefreshRates = setOf(30f, 90f)
+ summary.minRenderFrameRate = 60f
+ summary.maxRenderFrameRate = 120f
+
+ val result = summary.filterModes(arrayOf(createMode(1, 90f, 90f)))
+
+ assertThat(result).isEmpty()
+ }
+
+ @Test
+ fun `summary invalid if has requestedRefreshRate more than maxRenderFrameRate`() {
+ val summary = createSummary()
+ summary.requestedRefreshRates = setOf(60f, 240f)
+ summary.minRenderFrameRate = 60f
+ summary.maxRenderFrameRate = 120f
+
+ val result = summary.filterModes(arrayOf(createMode(1, 90f, 90f)))
+
+ assertThat(result).isEmpty()
+ }
+
+ @Test
+ fun `summary valid if all requestedRefreshRates inside render rate limits`() {
+ val summary = createSummary()
+ summary.requestedRefreshRates = setOf(60f, 90f)
+ summary.minRenderFrameRate = 60f
+ summary.maxRenderFrameRate = 120f
+
+ val result = summary.filterModes(arrayOf(createMode(1, 90f, 90f)))
+
+ assertThat(result).hasSize(1)
+ }
}
+
+
private fun createMode(modeId: Int, refreshRate: Float, vsyncRate: Float): Display.Mode {
return Display.Mode(modeId, 600, 800, refreshRate, vsyncRate, false,
FloatArray(0), IntArray(0))
}
-private fun createSummary(supportedModesVoteEnabled: Boolean): VoteSummary {
+private fun createSummary(supportedModesVoteEnabled: Boolean = false): VoteSummary {
val summary = createVotesSummary(supportedModesVoteEnabled = supportedModesVoteEnabled)
summary.width = 600
summary.height = 800