Merge changes from topic "preferredDisplayModeId60120" into sc-dev

* changes:
  Enable preferredDisplayModeId for frame rate override
  Add preferredMaxDisplayRefreshRate
This commit is contained in:
Ady Abraham
2021-05-13 15:59:00 +00:00
committed by Android (Google) Code Review
12 changed files with 858 additions and 186 deletions

View File

@@ -190,6 +190,8 @@ public abstract class DisplayManagerInternal {
* has a preference.
* @param requestedModeId The preferred mode id for the top-most visible window that has a
* preference.
* @param requestedMaxRefreshRate The preferred highest refresh rate for the top-most visible
* window that has a preference.
* @param requestedMinimalPostProcessing The preferred minimal post processing setting for the
* display. This is true when there is at least one visible window that wants minimal post
* processng on.
@@ -197,8 +199,8 @@ public abstract class DisplayManagerInternal {
* prior to call to performTraversalInTransactionFromWindowManager.
*/
public abstract void setDisplayProperties(int displayId, boolean hasContent,
float requestedRefreshRate, int requestedModeId, boolean requestedMinimalPostProcessing,
boolean inTraversal);
float requestedRefreshRate, int requestedModeId, float requestedMaxRefreshRate,
boolean requestedMinimalPostProcessing, boolean inTraversal);
/**
* Applies an offset to the contents of a display, for example to avoid burn-in.

View File

@@ -3009,6 +3009,14 @@ public interface WindowManager extends ViewManager {
*/
public int preferredDisplayModeId;
/**
* The max display refresh rate while the window is in focus.
*
* This value is ignored if {@link #preferredDisplayModeId} is set.
* @hide
*/
public float preferredMaxDisplayRefreshRate;
/**
* An internal annotation for flags that can be specified to {@link #systemUiVisibility}
* and {@link #subtreeSystemUiVisibility}.

View File

@@ -61,7 +61,6 @@ import java.io.PrintWriter;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Consumer;
@@ -85,7 +84,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
private final LayoutParams mLpChanged;
private final boolean mKeyguardScreenRotation;
private final long mLockScreenDisplayTimeout;
private final Display.Mode mKeyguardDisplayMode;
private final float mKeyguardRefreshRate;
private final KeyguardViewMediator mKeyguardViewMediator;
private final KeyguardBypassController mKeyguardBypassController;
private ViewGroup mNotificationShadeView;
@@ -135,14 +134,8 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
// Running on the highest frame rate available can be expensive.
// Let's specify a preferred refresh rate, and allow higher FPS only when we
// know that we're not falsing (because we unlocked.)
int keyguardRefreshRate = context.getResources()
mKeyguardRefreshRate = context.getResources()
.getInteger(R.integer.config_keyguardRefreshRate);
// Find supported display mode with the same resolution and requested refresh rate.
mKeyguardDisplayMode = Arrays.stream(supportedModes).filter(mode ->
(int) mode.getRefreshRate() == keyguardRefreshRate
&& mode.getPhysicalWidth() == currentMode.getPhysicalWidth()
&& mode.getPhysicalHeight() == currentMode.getPhysicalHeight())
.findFirst().orElse(null);
}
/**
@@ -273,16 +266,17 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
mLpChanged.privateFlags &= ~LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
}
if (mKeyguardDisplayMode != null) {
if (mKeyguardRefreshRate > 0) {
boolean bypassOnKeyguard = mKeyguardBypassController.getBypassEnabled()
&& state.mStatusBarState == StatusBarState.KEYGUARD
&& !state.mKeyguardFadingAway && !state.mKeyguardGoingAway;
if (state.mDozing || bypassOnKeyguard) {
mLpChanged.preferredDisplayModeId = mKeyguardDisplayMode.getModeId();
mLpChanged.preferredMaxDisplayRefreshRate = mKeyguardRefreshRate;
} else {
mLpChanged.preferredDisplayModeId = 0;
mLpChanged.preferredMaxDisplayRefreshRate = 0;
}
Trace.setCounter("display_mode_id", mLpChanged.preferredDisplayModeId);
Trace.setCounter("display_max_refresh_rate",
(long) mLpChanged.preferredMaxDisplayRefreshRate);
}
}
@@ -669,7 +663,7 @@ public class NotificationShadeWindowControllerImpl implements NotificationShadeW
@Override
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println(TAG + ":");
pw.println(" mKeyguardDisplayMode=" + mKeyguardDisplayMode);
pw.println(" mKeyguardRefreshRate=" + mKeyguardRefreshRate);
pw.println(mCurrentState);
if (mNotificationShadeView != null && mNotificationShadeView.getViewRootImpl() != null) {
mNotificationShadeView.getViewRootImpl().dump(" ", pw);

View File

@@ -1498,8 +1498,8 @@ public final class DisplayManagerService extends SystemService {
}
private void setDisplayPropertiesInternal(int displayId, boolean hasContent,
float requestedRefreshRate, int requestedModeId, boolean preferMinimalPostProcessing,
boolean inTraversal) {
float requestedRefreshRate, int requestedModeId, float requestedMaxRefreshRate,
boolean preferMinimalPostProcessing, boolean inTraversal) {
synchronized (mSyncRoot) {
final LogicalDisplay display = mLogicalDisplayMapper.getDisplayLocked(displayId);
if (display == null) {
@@ -1523,8 +1523,8 @@ public final class DisplayManagerService extends SystemService {
requestedModeId = display.getDisplayInfoLocked().findDefaultModeByRefreshRate(
requestedRefreshRate).getModeId();
}
mDisplayModeDirector.getAppRequestObserver().setAppRequestedMode(
displayId, requestedModeId);
mDisplayModeDirector.getAppRequestObserver().setAppRequest(
displayId, requestedModeId, requestedMaxRefreshRate);
if (display.getDisplayInfoLocked().minimalPostProcessingSupported) {
boolean mppRequest = mMinimalPostProcessingAllowed && preferMinimalPostProcessing;
@@ -3189,10 +3189,11 @@ public final class DisplayManagerService extends SystemService {
@Override
public void setDisplayProperties(int displayId, boolean hasContent,
float requestedRefreshRate, int requestedMode,
float requestedRefreshRate, int requestedMode, float requestedMaxRefreshRate,
boolean requestedMinimalPostProcessing, boolean inTraversal) {
setDisplayPropertiesInternal(displayId, hasContent, requestedRefreshRate,
requestedMode, requestedMinimalPostProcessing, inTraversal);
requestedMode, requestedMaxRefreshRate, requestedMinimalPostProcessing,
inTraversal);
}
@Override

View File

@@ -198,6 +198,8 @@ public class DisplayModeDirector {
public float maxRefreshRate;
public int width;
public int height;
public boolean disableRefreshRateSwitching;
public float baseModeRefreshRate;
VoteSummary() {
reset();
@@ -208,6 +210,8 @@ public class DisplayModeDirector {
maxRefreshRate = Float.POSITIVE_INFINITY;
width = Vote.INVALID_SIZE;
height = Vote.INVALID_SIZE;
disableRefreshRateSwitching = false;
baseModeRefreshRate = 0f;
}
}
@@ -229,13 +233,20 @@ public class DisplayModeDirector {
// 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).
// 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).
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;
}
if (!summary.disableRefreshRateSwitching && vote.disableRefreshRateSwitching) {
summary.disableRefreshRateSwitching = true;
}
if (summary.baseModeRefreshRate == 0f && vote.baseModeRefreshRate > 0f) {
summary.baseModeRefreshRate = vote.baseModeRefreshRate;
}
}
}
@@ -260,13 +271,14 @@ public class DisplayModeDirector {
return new DesiredDisplayModeSpecs();
}
int[] availableModes = new int[]{defaultMode.getModeId()};
ArrayList<Display.Mode> availableModes = new ArrayList<>();
availableModes.add(defaultMode);
VoteSummary primarySummary = new VoteSummary();
int lowestConsideredPriority = Vote.MIN_PRIORITY;
int highestConsideredPriority = Vote.MAX_PRIORITY;
if (mAlwaysRespectAppRequest) {
lowestConsideredPriority = Vote.PRIORITY_APP_REQUEST_REFRESH_RATE;
lowestConsideredPriority = Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE;
highestConsideredPriority = Vote.PRIORITY_APP_REQUEST_SIZE;
}
@@ -286,16 +298,19 @@ public class DisplayModeDirector {
}
availableModes = filterModes(modes, primarySummary);
if (availableModes.length > 0) {
if (!availableModes.isEmpty()) {
if (mLoggingEnabled) {
Slog.w(TAG, "Found available modes=" + Arrays.toString(availableModes)
Slog.w(TAG, "Found available modes=" + availableModes
+ " with lowest priority considered "
+ Vote.priorityToString(lowestConsideredPriority)
+ " and constraints: "
+ "width=" + primarySummary.width
+ ", height=" + primarySummary.height
+ ", minRefreshRate=" + primarySummary.minRefreshRate
+ ", maxRefreshRate=" + primarySummary.maxRefreshRate);
+ ", maxRefreshRate=" + primarySummary.maxRefreshRate
+ ", disableRefreshRateSwitching="
+ primarySummary.disableRefreshRateSwitching
+ ", baseModeRefreshRate=" + primarySummary.baseModeRefreshRate);
}
break;
}
@@ -307,7 +322,10 @@ public class DisplayModeDirector {
+ "width=" + primarySummary.width
+ ", height=" + primarySummary.height
+ ", minRefreshRate=" + primarySummary.minRefreshRate
+ ", maxRefreshRate=" + primarySummary.maxRefreshRate);
+ ", maxRefreshRate=" + primarySummary.maxRefreshRate
+ ", disableRefreshRateSwitching="
+ primarySummary.disableRefreshRateSwitching
+ ", baseModeRefreshRate=" + primarySummary.baseModeRefreshRate);
}
// If we haven't found anything with the current set of votes, drop the
@@ -332,26 +350,38 @@ public class DisplayModeDirector {
appRequestSummary.maxRefreshRate));
}
int baseModeId = INVALID_DISPLAY_MODE_ID;
// 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.
Display.Mode baseMode = null;
for (Display.Mode availableMode : availableModes) {
if (primarySummary.baseModeRefreshRate
>= availableMode.getRefreshRate() - FLOAT_TOLERANCE
&& primarySummary.baseModeRefreshRate
<= availableMode.getRefreshRate() + FLOAT_TOLERANCE) {
baseMode = availableMode;
}
}
// Select the default mode if available. This is important because SurfaceFlinger
// can do only seamless switches by default. Some devices (e.g. TV) don't support
// seamless switching so the mode we select here won't be changed.
for (int availableMode : availableModes) {
if (availableMode == defaultMode.getModeId()) {
baseModeId = defaultMode.getModeId();
break;
if (baseMode == null) {
for (Display.Mode availableMode : availableModes) {
if (availableMode.getModeId() == defaultMode.getModeId()) {
baseMode = defaultMode;
break;
}
}
}
// If the application requests a display mode by setting
// LayoutParams.preferredDisplayModeId, it will be the only available mode and it'll
// be stored as baseModeId.
if (baseModeId == INVALID_DISPLAY_MODE_ID && availableModes.length > 0) {
baseModeId = availableModes[0];
if (baseMode == null && !availableModes.isEmpty()) {
baseMode = availableModes.get(0);
}
if (baseModeId == INVALID_DISPLAY_MODE_ID) {
if (baseMode == null) {
Slog.w(TAG, "Can't find a set of allowed modes which satisfies the votes. Falling"
+ " back to the default mode. Display = " + displayId + ", votes = " + votes
+ ", supported modes = " + Arrays.toString(modes));
@@ -363,31 +393,19 @@ public class DisplayModeDirector {
new RefreshRateRange(fps, fps));
}
if (mModeSwitchingType == DisplayManager.SWITCHING_TYPE_NONE) {
Display.Mode baseMode = null;
for (Display.Mode mode : modes) {
if (mode.getModeId() == baseModeId) {
baseMode = mode;
break;
}
}
if (baseMode == null) {
// This should never happen.
throw new IllegalStateException(
"The base mode with id " + baseModeId
+ " is not in the list of supported modes.");
}
if (mModeSwitchingType == DisplayManager.SWITCHING_TYPE_NONE
|| primarySummary.disableRefreshRateSwitching) {
float fps = baseMode.getRefreshRate();
return new DesiredDisplayModeSpecs(baseModeId,
/*allowGroupSwitching */ false,
new RefreshRateRange(fps, fps),
new RefreshRateRange(fps, fps));
primarySummary.minRefreshRate = primarySummary.maxRefreshRate = fps;
if (mModeSwitchingType == DisplayManager.SWITCHING_TYPE_NONE) {
appRequestSummary.minRefreshRate = appRequestSummary.maxRefreshRate = fps;
}
}
boolean allowGroupSwitching =
mModeSwitchingType == DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS;
return new DesiredDisplayModeSpecs(baseModeId,
return new DesiredDisplayModeSpecs(baseMode.getModeId(),
allowGroupSwitching,
new RefreshRateRange(
primarySummary.minRefreshRate, primarySummary.maxRefreshRate),
@@ -396,8 +414,10 @@ public class DisplayModeDirector {
}
}
private int[] filterModes(Display.Mode[] supportedModes, VoteSummary summary) {
private ArrayList<Display.Mode> filterModes(Display.Mode[] supportedModes,
VoteSummary summary) {
ArrayList<Display.Mode> availableModes = new ArrayList<>();
boolean missingBaseModeRefreshRate = summary.baseModeRefreshRate > 0f;
for (Display.Mode mode : supportedModes) {
if (mode.getPhysicalWidth() != summary.width
|| mode.getPhysicalHeight() != summary.height) {
@@ -426,13 +446,16 @@ public class DisplayModeDirector {
continue;
}
availableModes.add(mode);
if (mode.getRefreshRate() >= summary.baseModeRefreshRate - FLOAT_TOLERANCE
&& mode.getRefreshRate() <= summary.baseModeRefreshRate + FLOAT_TOLERANCE) {
missingBaseModeRefreshRate = false;
}
}
final int size = availableModes.size();
int[] availableModeIds = new int[size];
for (int i = 0; i < size; i++) {
availableModeIds[i] = availableModes.get(i).getModeId();
if (missingBaseModeRefreshRate) {
return new ArrayList<>();
}
return availableModeIds;
return availableModes;
}
/**
@@ -912,37 +935,52 @@ public class DisplayModeDirector {
// by all other considerations. It acts to set a default frame rate for a device.
public static final int PRIORITY_DEFAULT_REFRESH_RATE = 0;
// FLICKER votes for a single refresh rate like [60,60], [90,90] or null.
// If the higher voters result is a range, it will fix the rate to a single choice.
// It's used to avoid refresh rate switches in certain conditions which may result in the
// user seeing the display flickering when the switches occur.
public static final int PRIORITY_FLICKER = 1;
// 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
// result is a range.
public static final int PRIORITY_FLICKER_REFRESH_RATE = 1;
// SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate.
// It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
public static final int PRIORITY_USER_SETTING_MIN_REFRESH_RATE = 2;
// APP_REQUEST_MAX_REFRESH_RATE is used to for internal apps to limit the refresh
// rate in certain cases, mostly to preserve power.
// It votes to [0, APP_REQUEST_MAX_REFRESH_RATE].
public static final int PRIORITY_APP_REQUEST_MAX_REFRESH_RATE = 3;
// We split the app request into different priorities in case we can satisfy one desire
// without the other.
// Application can specify preferred refresh rate with below attrs.
// @see android.view.WindowManager.LayoutParams#preferredRefreshRate
// @see android.view.WindowManager.LayoutParams#preferredDisplayModeId
// System also forces some apps like denylisted app to run at a lower refresh rate.
// These translates into votes for the base mode refresh rate and resolution to be
// used by SurfaceFlinger as the policy of choosing the display mode. The system also
// forces some apps like denylisted app to run at a lower refresh rate.
// @see android.R.array#config_highRefreshRateBlacklist
public static final int PRIORITY_APP_REQUEST_REFRESH_RATE = 3;
public static final int PRIORITY_APP_REQUEST_SIZE = 4;
// The preferred refresh rate is set on the main surface of the app outside of
// DisplayModeDirector.
// @see com.android.server.wm.WindowState#updateFrameRateSelectionPriorityIfNeeded
public static final int PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE = 4;
public static final int PRIORITY_APP_REQUEST_SIZE = 5;
// 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 = 5;
public static final int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 6;
// LOW_POWER_MODE force display to [0, 60HZ] if Settings.Global.LOW_POWER_MODE is on.
public static final int PRIORITY_LOW_POWER_MODE = 6;
public static final int PRIORITY_LOW_POWER_MODE = 7;
// PRIORITY_FLICKER_REFRESH_RATE_SWITCH votes for disabling refresh rate switching. If the
// higher priority voters' result is a range, it will fix the rate to a single choice.
// It's used to avoid refresh rate switches in certain conditions which may result in the
// user seeing the display flickering when the switches occur.
public static final int PRIORITY_FLICKER_REFRESH_RATE_SWITCH = 8;
// The Under-Display Fingerprint Sensor (UDFPS) needs the refresh rate to be locked in order
// to function, so this needs to be the highest priority of all votes.
public static final int PRIORITY_UDFPS = 7;
public static final int PRIORITY_UDFPS = 9;
// 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.
@@ -953,7 +991,7 @@ public class DisplayModeDirector {
// 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;
PRIORITY_APP_REQUEST_MAX_REFRESH_RATE;
/**
* A value signifying an invalid width or height in a vote.
@@ -973,32 +1011,64 @@ public class DisplayModeDirector {
*/
public final RefreshRateRange refreshRateRange;
/**
* Whether refresh rate switching should be disabled (i.e. the refresh rate range is
* a single value).
*/
public final boolean disableRefreshRateSwitching;
/**
* The base mode refresh rate to be used for this display. This would be used when deciding
* the base mode id.
*/
public final float baseModeRefreshRate;
public static Vote forRefreshRates(float minRefreshRate, float maxRefreshRate) {
return new Vote(INVALID_SIZE, INVALID_SIZE, minRefreshRate, maxRefreshRate);
return new Vote(INVALID_SIZE, INVALID_SIZE, minRefreshRate, maxRefreshRate,
minRefreshRate == maxRefreshRate, 0f);
}
public static Vote forSize(int width, int height) {
return new Vote(width, height, 0f, Float.POSITIVE_INFINITY);
return new Vote(width, height, 0f, Float.POSITIVE_INFINITY, false,
0f);
}
public static Vote forDisableRefreshRateSwitching() {
return new Vote(INVALID_SIZE, INVALID_SIZE, 0f, Float.POSITIVE_INFINITY, true,
0f);
}
public static Vote forBaseModeRefreshRate(float baseModeRefreshRate) {
return new Vote(INVALID_SIZE, INVALID_SIZE, 0f, Float.POSITIVE_INFINITY, false,
baseModeRefreshRate);
}
private Vote(int width, int height,
float minRefreshRate, float maxRefreshRate) {
float minRefreshRate, float maxRefreshRate,
boolean disableRefreshRateSwitching,
float baseModeRefreshRate) {
this.width = width;
this.height = height;
this.refreshRateRange =
new RefreshRateRange(minRefreshRate, maxRefreshRate);
this.disableRefreshRateSwitching = disableRefreshRateSwitching;
this.baseModeRefreshRate = baseModeRefreshRate;
}
public static String priorityToString(int priority) {
switch (priority) {
case PRIORITY_DEFAULT_REFRESH_RATE:
return "PRIORITY_DEFAULT_REFRESH_RATE";
case PRIORITY_FLICKER:
return "PRIORITY_FLICKER";
case PRIORITY_FLICKER_REFRESH_RATE:
return "PRIORITY_FLICKER_REFRESH_RATE";
case PRIORITY_FLICKER_REFRESH_RATE_SWITCH:
return "PRIORITY_FLICKER_REFRESH_RATE_SWITCH";
case PRIORITY_USER_SETTING_MIN_REFRESH_RATE:
return "PRIORITY_USER_SETTING_MIN_REFRESH_RATE";
case PRIORITY_APP_REQUEST_REFRESH_RATE:
return "PRIORITY_APP_REQUEST_REFRESH_RATE";
case PRIORITY_APP_REQUEST_MAX_REFRESH_RATE:
return "PRIORITY_APP_REQUEST_MAX_REFRESH_RATE";
case PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE:
return "PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE";
case PRIORITY_APP_REQUEST_SIZE:
return "PRIORITY_APP_REQUEST_SIZE";
case PRIORITY_USER_SETTING_PEAK_REFRESH_RATE:
@@ -1018,7 +1088,9 @@ public class DisplayModeDirector {
return "Vote{"
+ "width=" + width + ", height=" + height
+ ", minRefreshRate=" + refreshRateRange.min
+ ", maxRefreshRate=" + refreshRateRange.max + "}";
+ ", maxRefreshRate=" + refreshRateRange.max
+ ", disableRefreshRateSwitching=" + disableRefreshRateSwitching
+ ", baseModeRefreshRate=" + baseModeRefreshRate + "}";
}
}
@@ -1182,14 +1254,17 @@ public class DisplayModeDirector {
final class AppRequestObserver {
private final SparseArray<Display.Mode> mAppRequestedModeByDisplay;
private final SparseArray<Float> mAppPreferredMaxRefreshRateByDisplay;
AppRequestObserver() {
mAppRequestedModeByDisplay = new SparseArray<>();
mAppPreferredMaxRefreshRateByDisplay = new SparseArray<>();
}
public void setAppRequestedMode(int displayId, int modeId) {
public void setAppRequest(int displayId, int modeId, float requestedMaxRefreshRate) {
synchronized (mLock) {
setAppRequestedModeLocked(displayId, modeId);
setAppPreferredMaxRefreshRateLocked(displayId, requestedMaxRefreshRate);
}
}
@@ -1199,24 +1274,48 @@ public class DisplayModeDirector {
return;
}
final Vote refreshRateVote;
final Vote baseModeRefreshRateVote;
final Vote sizeVote;
if (requestedMode != null) {
mAppRequestedModeByDisplay.put(displayId, requestedMode);
float refreshRate = requestedMode.getRefreshRate();
refreshRateVote = Vote.forRefreshRates(refreshRate, refreshRate);
baseModeRefreshRateVote =
Vote.forBaseModeRefreshRate(requestedMode.getRefreshRate());
sizeVote = Vote.forSize(requestedMode.getPhysicalWidth(),
requestedMode.getPhysicalHeight());
} else {
mAppRequestedModeByDisplay.remove(displayId);
refreshRateVote = null;
baseModeRefreshRateVote = null;
sizeVote = null;
}
updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, refreshRateVote);
updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
baseModeRefreshRateVote);
updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_SIZE, sizeVote);
}
private void setAppPreferredMaxRefreshRateLocked(int displayId,
float requestedMaxRefreshRate) {
final Vote vote;
final Float requestedMaxRefreshRateVote =
requestedMaxRefreshRate > 0
? new Float(requestedMaxRefreshRate) : null;
if (Objects.equals(requestedMaxRefreshRateVote,
mAppPreferredMaxRefreshRateByDisplay.get(displayId))) {
return;
}
if (requestedMaxRefreshRate > 0) {
mAppPreferredMaxRefreshRateByDisplay.put(displayId, requestedMaxRefreshRateVote);
vote = Vote.forRefreshRates(0, requestedMaxRefreshRate);
} else {
mAppPreferredMaxRefreshRateByDisplay.remove(displayId);
vote = null;
}
synchronized (mLock) {
updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_MAX_REFRESH_RATE, vote);
}
}
private Display.Mode findModeByIdLocked(int displayId, int modeId) {
Display.Mode[] modes = mSupportedModesByDisplay.get(displayId);
if (modes == null) {
@@ -1238,6 +1337,12 @@ public class DisplayModeDirector {
final Display.Mode mode = mAppRequestedModeByDisplay.valueAt(i);
pw.println(" " + id + " -> " + mode);
}
pw.println(" mAppPreferredMaxRefreshRateByDisplay:");
for (int i = 0; i < mAppPreferredMaxRefreshRateByDisplay.size(); i++) {
final int id = mAppPreferredMaxRefreshRateByDisplay.keyAt(i);
final Float refreshRate = mAppPreferredMaxRefreshRateByDisplay.valueAt(i);
pw.println(" " + id + " -> " + refreshRate);
}
}
}
@@ -1486,7 +1591,8 @@ public class DisplayModeDirector {
updateSensorStatus();
if (!changeable) {
// Revoke previous vote from BrightnessObserver
updateVoteLocked(Vote.PRIORITY_FLICKER, null);
updateVoteLocked(Vote.PRIORITY_FLICKER_REFRESH_RATE, null);
updateVoteLocked(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, null);
}
}
}
@@ -1734,7 +1840,8 @@ public class DisplayModeDirector {
return false;
}
private void onBrightnessChangedLocked() {
Vote vote = null;
Vote refreshRateVote = null;
Vote refreshRateSwitchingVote = null;
if (mBrightness < 0) {
// Either the setting isn't available or we shouldn't be observing yet anyways.
@@ -1744,20 +1851,25 @@ public class DisplayModeDirector {
boolean insideLowZone = hasValidLowZone() && isInsideLowZone(mBrightness, mAmbientLux);
if (insideLowZone) {
vote = Vote.forRefreshRates(mRefreshRateInLowZone, mRefreshRateInLowZone);
refreshRateVote =
Vote.forRefreshRates(mRefreshRateInLowZone, mRefreshRateInLowZone);
refreshRateSwitchingVote = Vote.forDisableRefreshRateSwitching();
}
boolean insideHighZone = hasValidHighZone()
&& isInsideHighZone(mBrightness, mAmbientLux);
if (insideHighZone) {
vote = Vote.forRefreshRates(mRefreshRateInHighZone, mRefreshRateInHighZone);
refreshRateVote =
Vote.forRefreshRates(mRefreshRateInHighZone, mRefreshRateInHighZone);
refreshRateSwitchingVote = Vote.forDisableRefreshRateSwitching();
}
if (mLoggingEnabled) {
Slog.d(TAG, "Display brightness " + mBrightness + ", ambient lux " + mAmbientLux
+ ", Vote " + vote);
+ ", Vote " + refreshRateVote);
}
updateVoteLocked(Vote.PRIORITY_FLICKER, vote);
updateVoteLocked(Vote.PRIORITY_FLICKER_REFRESH_RATE, refreshRateVote);
updateVoteLocked(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, refreshRateSwitchingVote);
}
private boolean hasValidLowZone() {

View File

@@ -901,6 +901,14 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
&& preferredModeId != 0) {
mTmpApplySurfaceChangesTransactionState.preferredModeId = preferredModeId;
}
final float preferredMaxRefreshRate = getDisplayPolicy().getRefreshRatePolicy()
.getPreferredMaxRefreshRate(w);
if (mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate == 0
&& preferredMaxRefreshRate != 0) {
mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate =
preferredMaxRefreshRate;
}
}
}
@@ -4230,6 +4238,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
mLastHasContent,
mTmpApplySurfaceChangesTransactionState.preferredRefreshRate,
mTmpApplySurfaceChangesTransactionState.preferredModeId,
mTmpApplySurfaceChangesTransactionState.preferredMaxRefreshRate,
mTmpApplySurfaceChangesTransactionState.preferMinimalPostProcessing,
true /* inTraversal, must call performTraversalInTrans... below */);
}
@@ -4513,12 +4522,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
}
private static final class ApplySurfaceChangesTransactionState {
boolean displayHasContent;
boolean obscured;
boolean syswin;
boolean preferMinimalPostProcessing;
float preferredRefreshRate;
int preferredModeId;
public boolean displayHasContent;
public boolean obscured;
public boolean syswin;
public boolean preferMinimalPostProcessing;
public float preferredRefreshRate;
public int preferredModeId;
public float preferredMaxRefreshRate;
void reset() {
displayHasContent = false;
@@ -4527,6 +4537,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
preferMinimalPostProcessing = false;
preferredRefreshRate = 0;
preferredModeId = 0;
preferredMaxRefreshRate = 0;
}
}

View File

@@ -20,6 +20,7 @@ import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
import android.util.ArraySet;
import android.view.Display;
import android.view.Display.Mode;
import android.view.DisplayInfo;
@@ -95,18 +96,10 @@ class RefreshRatePolicy {
return 0;
}
// If app requests a certain refresh rate or mode, don't override it.
if (w.mAttrs.preferredRefreshRate != 0 || w.mAttrs.preferredDisplayModeId != 0) {
return w.mAttrs.preferredDisplayModeId;
}
final String packageName = w.getOwningPackage();
// If app is using Camera, force it to default (lower) refresh rate.
if (mNonHighRefreshRatePackages.contains(packageName)) {
return mLowRefreshRateMode.getModeId();
}
return 0;
}
@@ -145,6 +138,44 @@ class RefreshRatePolicy {
if (mHighRefreshRateDenylist.isDenylisted(packageName)) {
return mLowRefreshRateMode.getRefreshRate();
}
final int preferredModeId = getPreferredModeId(w);
if (preferredModeId > 0) {
DisplayInfo info = w.getDisplayInfo();
if (info != null) {
for (Display.Mode mode : info.supportedModes) {
if (preferredModeId == mode.getModeId()) {
return mode.getRefreshRate();
}
}
}
}
return 0;
}
float getPreferredMaxRefreshRate(WindowState w) {
// If app is animating, it's not able to control refresh rate because we want the animation
// to run in default refresh rate.
if (w.isAnimating(TRANSITION | PARENTS)) {
return 0;
}
// If app requests a certain refresh rate or mode, don't override it.
if (w.mAttrs.preferredDisplayModeId != 0) {
return 0;
}
if (w.mAttrs.preferredMaxDisplayRefreshRate > 0) {
return w.mAttrs.preferredMaxDisplayRefreshRate;
}
final String packageName = w.getOwningPackage();
// If app is using Camera, force it to default (lower) refresh rate.
if (mNonHighRefreshRatePackages.contains(packageName)) {
return mLowRefreshRateMode.getRefreshRate();
}
return 0;
}
}

View File

@@ -751,11 +751,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
int mFrameRateSelectionPriority = RefreshRatePolicy.LAYER_PRIORITY_UNSET;
/**
* This is the frame rate which is passed to SurfaceFlinger if the window is part of the
* high refresh rate deny list. The variable is cached, so we do not send too many updates to
* SF.
* This is the frame rate which is passed to SurfaceFlinger if the window set a
* preferredDisplayModeId or is part of the high refresh rate deny list.
* The variable is cached, so we do not send too many updates to SF.
*/
float mDenyListFrameRate = 0f;
float mAppPreferredFrameRate = 0f;
static final int BLAST_TIMEOUT_DURATION = 5000; /* milliseconds */
@@ -5416,10 +5416,11 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP
}
final float refreshRate = refreshRatePolicy.getPreferredRefreshRate(this);
if (mDenyListFrameRate != refreshRate) {
mDenyListFrameRate = refreshRate;
if (mAppPreferredFrameRate != refreshRate) {
mAppPreferredFrameRate = refreshRate;
getPendingTransaction().setFrameRate(
mSurfaceControl, mDenyListFrameRate, Surface.FRAME_RATE_COMPATIBILITY_EXACT);
mSurfaceControl, mAppPreferredFrameRate,
Surface.FRAME_RATE_COMPATIBILITY_EXACT, Surface.CHANGE_FRAME_RATE_ALWAYS);
}
}

View File

@@ -23,10 +23,11 @@ import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REF
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_HIGH_ZONE;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_LOW_ZONE;
import static com.android.server.display.DisplayModeDirector.Vote.PRIORITY_FLICKER;
import static com.android.server.display.DisplayModeDirector.Vote.INVALID_SIZE;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -137,7 +138,14 @@ public class DisplayModeDirectorTest {
}
}
assertThat(defaultMode).isNotNull();
return createDirectorFromModeArray(modes, defaultMode);
}
private DisplayModeDirector createDirectorFromModeArray(Display.Mode[] modes,
Display.Mode defaultMode) {
DisplayModeDirector director =
new DisplayModeDirector(mContext, mHandler, mInjector);
director.setLoggingEnabled(true);
SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>();
supportedModesByDisplay.put(DISPLAY_ID, modes);
director.injectSupportedModesByDisplay(supportedModesByDisplay);
@@ -218,8 +226,9 @@ public class DisplayModeDirectorTest {
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_APP_REQUEST_SIZE, Vote.forRefreshRates(60 + error, 60 + error));
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE,
votes.put(Vote.PRIORITY_APP_REQUEST_SIZE,
Vote.forRefreshRates(60 + error, 60 + error));
votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
Vote.forRefreshRates(60 - error, 60 - error));
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
@@ -230,44 +239,159 @@ public class DisplayModeDirectorTest {
}
@Test
public void testFlickerHasLowerPriorityThanUser() {
assertTrue(PRIORITY_FLICKER < Vote.PRIORITY_APP_REQUEST_REFRESH_RATE);
assertTrue(PRIORITY_FLICKER < Vote.PRIORITY_APP_REQUEST_SIZE);
public void testFlickerHasLowerPriorityThanUserAndRangeIsSingle() {
assertTrue(Vote.PRIORITY_FLICKER_REFRESH_RATE
< Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
assertTrue(Vote.PRIORITY_FLICKER_REFRESH_RATE
< Vote.PRIORITY_APP_REQUEST_SIZE);
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
assertTrue(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH
> Vote.PRIORITY_LOW_POWER_MODE);
Display.Mode[] modes = new Display.Mode[4];
modes[0] = new Display.Mode(
/*modeId=*/1, /*width=*/1000, /*height=*/1000, 60);
modes[1] = new Display.Mode(
/*modeId=*/2, /*width=*/2000, /*height=*/2000, 60);
modes[2] = new Display.Mode(
/*modeId=*/3, /*width=*/1000, /*height=*/1000, 90);
modes[3] = new Display.Mode(
/*modeId=*/4, /*width=*/2000, /*height=*/2000, 90);
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_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 90));
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(60, 60));
Display.Mode appRequestedMode = modes[1];
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()));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forRefreshRates(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);
votes.clear();
appRequestedMode = modes[3];
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()));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forRefreshRates(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);
votes.clear();
appRequestedMode = modes[3];
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()));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forRefreshRates(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);
votes.clear();
appRequestedMode = modes[1];
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()));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forRefreshRates(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);
}
@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);
Display.Mode[] modes = new Display.Mode[4];
modes[0] = new Display.Mode(
/*modeId=*/1, /*width=*/1000, /*height=*/1000, 60);
modes[1] = new Display.Mode(
/*modeId=*/2, /*width=*/2000, /*height=*/2000, 60);
modes[2] = new Display.Mode(
/*modeId=*/3, /*width=*/1000, /*height=*/1000, 90);
modes[3] = new Display.Mode(
/*modeId=*/4, /*width=*/2000, /*height=*/2000, 90);
DisplayModeDirector director = createDirectorFromModeArray(modes, modes[0]);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
Display.Mode appRequestedMode = modes[1];
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()));
votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(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);
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 90));
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(90, 90));
appRequestedMode = modes[3];
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()));
votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(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);
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(90, 90));
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(60, 60));
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);
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(60, 60));
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(90, 90));
appRequestedMode = modes[3];
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()));
votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(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);
votes.clear();
appRequestedMode = modes[1];
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()));
votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(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);
}
@Test
@@ -275,19 +399,30 @@ public class DisplayModeDirectorTest {
// Confirm that the app request range doesn't include flicker or min refresh rate settings,
// but does include everything else.
assertTrue(
PRIORITY_FLICKER < Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
Vote.PRIORITY_FLICKER_REFRESH_RATE
< 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
assertTrue(Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE
>= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
Display.Mode[] modes = new Display.Mode[3];
modes[0] = new Display.Mode(
/*modeId=*/60, /*width=*/1000, /*height=*/1000, 60);
modes[1] = new Display.Mode(
/*modeId=*/75, /*width=*/2000, /*height=*/2000, 75);
modes[2] = new Display.Mode(
/*modeId=*/90, /*width=*/1000, /*height=*/1000, 90);
DisplayModeDirector director = createDirectorFromModeArray(modes, modes[0]);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(60, 60));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE, Vote.forRefreshRates(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);
@@ -297,22 +432,24 @@ public class DisplayModeDirectorTest {
Vote.forRefreshRates(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);
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(75, 75));
Display.Mode appRequestedMode = modes[1];
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()));
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)
.isWithin(FLOAT_TOLERANCE)
.of(75);
assertThat(desiredSpecs.appRequestRefreshRateRange.max)
.isWithin(FLOAT_TOLERANCE)
.of(75);
assertThat(desiredSpecs.appRequestRefreshRateRange.min).isAtMost(60f);
assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f);
}
void verifySpecsWithRefreshRateSettings(DisplayModeDirector director, float minFps,
@@ -374,18 +511,29 @@ public class DisplayModeDirectorTest {
@Test
public void testVotingWithAlwaysRespectAppRequest() {
DisplayModeDirector director = createDirectorFromFpsRange(50, 90);
Display.Mode[] modes = new Display.Mode[3];
modes[0] = new Display.Mode(
/*modeId=*/50, /*width=*/1000, /*height=*/1000, 50);
modes[1] = new Display.Mode(
/*modeId=*/60, /*width=*/1000, /*height=*/1000, 60);
modes[2] = new Display.Mode(
/*modeId=*/90, /*width=*/1000, /*height=*/1000, 90);
DisplayModeDirector director = createDirectorFromModeArray(modes, modes[0]);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
votes.put(PRIORITY_FLICKER, Vote.forRefreshRates(0, 60));
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_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(90, 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));
director.injectVotesByDisplay(votesByDisplay);
assertThat(director.shouldAlwaysRespectAppRequestedMode()).isFalse();
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
@@ -396,8 +544,8 @@ public class DisplayModeDirectorTest {
director.setShouldAlwaysRespectAppRequestedMode(true);
assertThat(director.shouldAlwaysRespectAppRequestedMode()).isTrue();
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.primaryRefreshRateRange.min).isAtMost(50);
assertThat(desiredSpecs.primaryRefreshRateRange.max).isAtLeast(90);
assertThat(desiredSpecs.baseModeId).isEqualTo(90);
director.setShouldAlwaysRespectAppRequestedMode(false);
@@ -497,7 +645,8 @@ public class DisplayModeDirectorTest {
// Inject votes
SparseArray<Vote> votes = new SparseArray<>();
votes.put(Vote.PRIORITY_APP_REQUEST_SIZE, Vote.forSize(1920, 1080));
votes.put(Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, Vote.forRefreshRates(50, 50));
votes.put(Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE,
Vote.forBaseModeRefreshRate(60));
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
director.injectVotesByDisplay(votesByDisplay);
@@ -592,14 +741,19 @@ public class DisplayModeDirectorTest {
// Sensor reads 20 lux,
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 20 /*lux*/));
Vote vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE);
assertVoteForRefreshRate(vote, 90 /*fps*/);
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH);
assertThat(vote).isNotNull();
assertThat(vote.disableRefreshRateSwitching).isTrue();
setBrightness(125);
// Sensor reads 1000 lux,
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 1000 /*lux*/));
vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE);
assertThat(vote).isNull();
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH);
assertThat(vote).isNull();
}
@@ -635,15 +789,20 @@ public class DisplayModeDirectorTest {
// Sensor reads 2000 lux,
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 2000));
Vote vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
Vote vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE);
assertThat(vote).isNull();
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH);
assertThat(vote).isNull();
setBrightness(255);
// Sensor reads 9000 lux,
listener.onSensorChanged(TestUtils.createSensorEvent(lightSensor, 9000));
vote = director.getVote(Display.DEFAULT_DISPLAY, PRIORITY_FLICKER);
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE);
assertVoteForRefreshRate(vote, 60 /*fps*/);
vote = director.getVote(Display.DEFAULT_DISPLAY, Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH);
assertThat(vote).isNotNull();
assertThat(vote.disableRefreshRateSwitching).isTrue();
}
@Test
@@ -724,6 +883,336 @@ public class DisplayModeDirectorTest {
assertNull(vote);
}
@Test
public void testAppRequestMaxRefreshRate() {
// 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_MAX_REFRESH_RATE
>= Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF);
Display.Mode[] modes = new Display.Mode[3];
modes[0] = new Display.Mode(
/*modeId=*/60, /*width=*/1000, /*height=*/1000, 60);
modes[1] = new Display.Mode(
/*modeId=*/75, /*width=*/1000, /*height=*/1000, 75);
modes[2] = new Display.Mode(
/*modeId=*/90, /*width=*/1000, /*height=*/1000, 90);
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));
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);
votes.put(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE,
Vote.forRefreshRates(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_MAX_REFRESH_RATE, Vote.forRefreshRates(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);
}
@Test
public void testAppRequestObserver_modeId() {
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
director.getAppRequestObserver().setAppRequest(DISPLAY_ID, 60, 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.disableRefreshRateSwitching).isFalse();
assertThat(appRequestRefreshRate.baseModeRefreshRate).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(appRequestRefreshRate.height).isEqualTo(INVALID_SIZE);
assertThat(appRequestRefreshRate.width).isEqualTo(INVALID_SIZE);
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.disableRefreshRateSwitching).isFalse();
assertThat(appRequestSize.baseModeRefreshRate).isZero();
assertThat(appRequestSize.height).isEqualTo(1000);
assertThat(appRequestSize.width).isEqualTo(1000);
Vote appRequestMaxRefreshRate =
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_MAX_REFRESH_RATE);
assertNull(appRequestMaxRefreshRate);
director.getAppRequestObserver().setAppRequest(DISPLAY_ID, 90, 0);
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.disableRefreshRateSwitching).isFalse();
assertThat(appRequestRefreshRate.baseModeRefreshRate).isWithin(FLOAT_TOLERANCE).of(90);
assertThat(appRequestRefreshRate.height).isEqualTo(INVALID_SIZE);
assertThat(appRequestRefreshRate.width).isEqualTo(INVALID_SIZE);
appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE);
assertNotNull(appRequestSize);
assertThat(appRequestSize.refreshRateRange.min).isZero();
assertThat(appRequestSize.refreshRateRange.max).isPositiveInfinity();
assertThat(appRequestSize.height).isEqualTo(1000);
assertThat(appRequestSize.width).isEqualTo(1000);
appRequestMaxRefreshRate =
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_MAX_REFRESH_RATE);
assertNull(appRequestMaxRefreshRate);
}
@Test
public void testAppRequestObserver_maxRefreshRate() {
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 90);
Vote appRequestRefreshRate =
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
assertNull(appRequestRefreshRate);
Vote appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE);
assertNull(appRequestSize);
Vote appRequestMaxRefreshRate =
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_MAX_REFRESH_RATE);
assertNotNull(appRequestMaxRefreshRate);
assertThat(appRequestMaxRefreshRate.refreshRateRange.min).isZero();
assertThat(appRequestMaxRefreshRate.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
assertThat(appRequestMaxRefreshRate.height).isEqualTo(INVALID_SIZE);
assertThat(appRequestMaxRefreshRate.width).isEqualTo(INVALID_SIZE);
director.getAppRequestObserver().setAppRequest(DISPLAY_ID, -1, 60);
appRequestRefreshRate =
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_BASE_MODE_REFRESH_RATE);
assertNull(appRequestRefreshRate);
appRequestSize = director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_SIZE);
assertNull(appRequestSize);
appRequestMaxRefreshRate =
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_MAX_REFRESH_RATE);
assertNotNull(appRequestMaxRefreshRate);
assertThat(appRequestMaxRefreshRate.refreshRateRange.min).isZero();
assertThat(appRequestMaxRefreshRate.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(appRequestMaxRefreshRate.height).isEqualTo(INVALID_SIZE);
assertThat(appRequestMaxRefreshRate.width).isEqualTo(INVALID_SIZE);
}
@Test
public void testAppRequestObserver_modeIdAndMaxRefreshRate() {
DisplayModeDirector director = createDirectorFromFpsRange(60, 90);
director.getAppRequestObserver().setAppRequest(DISPLAY_ID, 60, 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.disableRefreshRateSwitching).isFalse();
assertThat(appRequestRefreshRate.baseModeRefreshRate).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(appRequestRefreshRate.height).isEqualTo(INVALID_SIZE);
assertThat(appRequestRefreshRate.width).isEqualTo(INVALID_SIZE);
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.height).isEqualTo(1000);
assertThat(appRequestSize.width).isEqualTo(1000);
Vote appRequestMaxRefreshRate =
director.getVote(DISPLAY_ID, Vote.PRIORITY_APP_REQUEST_MAX_REFRESH_RATE);
assertNotNull(appRequestMaxRefreshRate);
assertThat(appRequestMaxRefreshRate.refreshRateRange.min).isZero();
assertThat(appRequestMaxRefreshRate.refreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90);
assertThat(appRequestMaxRefreshRate.height).isEqualTo(INVALID_SIZE);
assertThat(appRequestMaxRefreshRate.width).isEqualTo(INVALID_SIZE);
}
@Test
public void testAppRequestsIsTheDefaultMode() {
Display.Mode[] modes = new Display.Mode[2];
modes[0] = new Display.Mode(
/*modeId=*/1, /*width=*/1000, /*height=*/1000, 60);
modes[1] = new Display.Mode(
/*modeId=*/2, /*width=*/1000, /*height=*/1000, 90);
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);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
Display.Mode appRequestedMode = modes[1];
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()));
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);
}
@Test
public void testDisableRefreshRateSwitchingVote() {
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_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching());
votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(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.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));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching());
votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(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.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));
votes.put(Vote.PRIORITY_FLICKER_REFRESH_RATE_SWITCH, Vote.forDisableRefreshRateSwitching());
votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(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.baseModeId).isEqualTo(90);
}
@Test
public void testBaseModeIdInPrimaryRange() {
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));
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);
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));
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.baseModeId).isEqualTo(55);
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_MAX_REFRESH_RATE, Vote.forRefreshRates(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));
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.baseModeId).isEqualTo(55);
votes.clear();
votes.put(Vote.PRIORITY_APP_REQUEST_MAX_REFRESH_RATE, Vote.forRefreshRates(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));
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.baseModeId).isEqualTo(55);
}
@Test
public void testStaleAppVote() {
Display.Mode[] modes = new Display.Mode[4];
modes[0] = new Display.Mode(
/*modeId=*/1, /*width=*/1000, /*height=*/1000, 60);
modes[1] = new Display.Mode(
/*modeId=*/2, /*width=*/2000, /*height=*/2000, 60);
modes[2] = new Display.Mode(
/*modeId=*/3, /*width=*/1000, /*height=*/1000, 90);
modes[3] = new Display.Mode(
/*modeId=*/4, /*width=*/2000, /*height=*/2000, 90);
DisplayModeDirector director = createDirectorFromModeArray(modes, modes[0]);
SparseArray<Vote> votes = new SparseArray<>();
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
votesByDisplay.put(DISPLAY_ID, votes);
Display.Mode appRequestedMode = modes[3];
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()));
director.injectVotesByDisplay(votesByDisplay);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(4);
// Change mode Id's to simulate that a hotplug has occurred.
Display.Mode[] newModes = new Display.Mode[4];
newModes[0] = new Display.Mode(
/*modeId=*/5, /*width=*/1000, /*height=*/1000, 60);
newModes[1] = new Display.Mode(
/*modeId=*/6, /*width=*/2000, /*height=*/2000, 60);
newModes[2] = new Display.Mode(
/*modeId=*/7, /*width=*/1000, /*height=*/1000, 90);
newModes[3] = new Display.Mode(
/*modeId=*/8, /*width=*/2000, /*height=*/2000, 90);
SparseArray<Display.Mode[]> supportedModesByDisplay = new SparseArray<>();
supportedModesByDisplay.put(DISPLAY_ID, newModes);
director.injectSupportedModesByDisplay(supportedModesByDisplay);
SparseArray<Display.Mode> defaultModesByDisplay = new SparseArray<>();
defaultModesByDisplay.put(DISPLAY_ID, newModes[0]);
director.injectDefaultModeByDisplay(defaultModesByDisplay);
desiredSpecs = director.getDesiredDisplayModeSpecs(DISPLAY_ID);
assertThat(desiredSpecs.baseModeId).isEqualTo(8);
}
private void assertVoteForRefreshRate(Vote vote, float refreshRate) {
assertThat(vote).isNotNull();
final DisplayModeDirector.RefreshRateRange expectedRange =

View File

@@ -77,12 +77,12 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase {
assertNotNull("Window state is created", appWindow);
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
appWindow.updateFrameRateSelectionPriorityIfNeeded();
// Priority doesn't change.
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
// Call the function a few times.
appWindow.updateFrameRateSelectionPriorityIfNeeded();
@@ -92,7 +92,7 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase {
verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority(
any(SurfaceControl.class), anyInt());
verify(appWindow.getPendingTransaction(), never()).setFrameRate(
any(SurfaceControl.class), anyInt(), anyInt());
any(SurfaceControl.class), anyInt(), anyInt(), anyInt());
}
@Test
@@ -101,16 +101,16 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase {
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
assertEquals(appWindow.getDisplayContent().getDisplayPolicy().getRefreshRatePolicy()
.getPreferredModeId(appWindow), 0);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.getDisplayContent().getDisplayPolicy().getRefreshRatePolicy()
.getPreferredRefreshRate(appWindow), 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
appWindow.updateFrameRateSelectionPriorityIfNeeded();
// Priority stays MAX_VALUE.
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority(
appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET);
@@ -119,38 +119,38 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase {
appWindow.updateFrameRateSelectionPriorityIfNeeded();
// Priority changes to 1.
assertEquals(appWindow.mFrameRateSelectionPriority, 1);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority(
appWindow.getSurfaceControl(), 1);
verify(appWindow.getPendingTransaction(), never()).setFrameRate(
any(SurfaceControl.class), anyInt(), anyInt());
any(SurfaceControl.class), anyInt(), anyInt(), anyInt());
}
@Test
public void testApplicationInFocusWithModeId() {
final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
// Application is in focus.
appWindow.mToken.mDisplayContent.mCurrentFocus = appWindow;
appWindow.updateFrameRateSelectionPriorityIfNeeded();
// Priority changes.
assertEquals(appWindow.mFrameRateSelectionPriority, 1);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
// Update the mode ID to a requested number.
appWindow.mAttrs.preferredDisplayModeId = 1;
appWindow.updateFrameRateSelectionPriorityIfNeeded();
// Priority changes.
assertEquals(appWindow.mFrameRateSelectionPriority, 0);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 60, FLOAT_TOLERANCE);
// Remove the mode ID request.
appWindow.mAttrs.preferredDisplayModeId = 0;
appWindow.updateFrameRateSelectionPriorityIfNeeded();
// Priority changes.
assertEquals(appWindow.mFrameRateSelectionPriority, 1);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
// Verify we called actions on Transactions correctly.
verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority(
@@ -160,14 +160,14 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase {
verify(appWindow.getPendingTransaction(), times(2)).setFrameRateSelectionPriority(
appWindow.getSurfaceControl(), 1);
verify(appWindow.getPendingTransaction(), never()).setFrameRate(
any(SurfaceControl.class), anyInt(), anyInt());
any(SurfaceControl.class), anyInt(), anyInt(), anyInt());
}
@Test
public void testApplicationNotInFocusWithModeId() {
final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
final WindowState inFocusWindow = createWindow(null, TYPE_APPLICATION, "inFocus");
appWindow.mToken.mDisplayContent.mCurrentFocus = inFocusWindow;
@@ -175,28 +175,28 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase {
appWindow.updateFrameRateSelectionPriorityIfNeeded();
// The window is not in focus.
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
// Update the mode ID to a requested number.
appWindow.mAttrs.preferredDisplayModeId = 1;
appWindow.updateFrameRateSelectionPriorityIfNeeded();
// Priority changes.
assertEquals(appWindow.mFrameRateSelectionPriority, 2);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 60, FLOAT_TOLERANCE);
verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority(
appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET);
verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority(
appWindow.getSurfaceControl(), 2);
verify(appWindow.getPendingTransaction(), never()).setFrameRate(
any(SurfaceControl.class), anyInt(), anyInt());
any(SurfaceControl.class), anyInt(), anyInt(), anyInt());
}
@Test
public void testApplicationNotInFocusWithoutModeId() {
final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow");
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
final WindowState inFocusWindow = createWindow(null, TYPE_APPLICATION, "inFocus");
appWindow.mToken.mDisplayContent.mCurrentFocus = inFocusWindow;
@@ -204,19 +204,19 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase {
appWindow.updateFrameRateSelectionPriorityIfNeeded();
// The window is not in focus.
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
// Make sure that the mode ID is not set.
appWindow.mAttrs.preferredDisplayModeId = 0;
appWindow.updateFrameRateSelectionPriorityIfNeeded();
// Priority doesn't change.
assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET);
assertEquals(appWindow.mDenyListFrameRate, 0, FLOAT_TOLERANCE);
assertEquals(appWindow.mAppPreferredFrameRate, 0, FLOAT_TOLERANCE);
verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority(
appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET);
verify(appWindow.getPendingTransaction(), never()).setFrameRate(
any(SurfaceControl.class), anyInt(), anyInt());
any(SurfaceControl.class), anyInt(), anyInt(), anyInt());
}
@Test
@@ -233,7 +233,7 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase {
appWindow.updateFrameRateSelectionPriorityIfNeeded();
assertEquals(RefreshRatePolicy.LAYER_PRIORITY_UNSET, appWindow.mFrameRateSelectionPriority);
assertEquals(60, appWindow.mDenyListFrameRate, FLOAT_TOLERANCE);
assertEquals(60, appWindow.mAppPreferredFrameRate, FLOAT_TOLERANCE);
// Call the function a few times.
appWindow.updateFrameRateSelectionPriorityIfNeeded();
@@ -243,6 +243,7 @@ public class FrameRateSelectionPriorityTests extends WindowTestsBase {
verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority(
any(SurfaceControl.class), anyInt());
verify(appWindow.getPendingTransaction(), times(1)).setFrameRate(
appWindow.getSurfaceControl(), 60, Surface.FRAME_RATE_COMPATIBILITY_EXACT);
appWindow.getSurfaceControl(), 60,
Surface.FRAME_RATE_COMPATIBILITY_EXACT, Surface.CHANGE_FRAME_RATE_ALWAYS);
}
}

View File

@@ -71,9 +71,11 @@ public class RefreshRatePolicyTest extends WindowTestsBase {
cameraUsingWindow.mAttrs.packageName = "com.android.test";
assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
mPolicy.addNonHighRefreshRatePackage("com.android.test");
assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(60, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
mPolicy.removeNonHighRefreshRatePackage("com.android.test");
assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
@@ -109,6 +111,7 @@ public class RefreshRatePolicyTest extends WindowTestsBase {
mPolicy.addNonHighRefreshRatePackage("com.android.test");
assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(overrideWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE);
}
@Test
@@ -123,6 +126,7 @@ public class RefreshRatePolicyTest extends WindowTestsBase {
mPolicy.addNonHighRefreshRatePackage("com.android.test");
assertEquals(0, mPolicy.getPreferredModeId(overrideWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE);
}
@Test
@@ -132,13 +136,31 @@ public class RefreshRatePolicyTest extends WindowTestsBase {
cameraUsingWindow.mAttrs.packageName = "com.android.test";
mPolicy.addNonHighRefreshRatePackage("com.android.test");
assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(60, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
cameraUsingWindow.mActivityRecord.mSurfaceAnimator.startAnimation(
cameraUsingWindow.getPendingTransaction(), mock(AnimationAdapter.class),
false /* hidden */, ANIMATION_TYPE_APP_TRANSITION);
assertEquals(0, mPolicy.getPreferredModeId(cameraUsingWindow));
assertEquals(0, mPolicy.getPreferredRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMaxRefreshRate(cameraUsingWindow), FLOAT_TOLERANCE);
}
@Test
public void testAppMaxRefreshRate() {
final WindowState window = createWindow(null, TYPE_BASE_APPLICATION, "window");
window.mAttrs.preferredMaxDisplayRefreshRate = 60f;
assertEquals(0, mPolicy.getPreferredModeId(window));
assertEquals(0, mPolicy.getPreferredRefreshRate(window), FLOAT_TOLERANCE);
assertEquals(60, mPolicy.getPreferredMaxRefreshRate(window), FLOAT_TOLERANCE);
window.mActivityRecord.mSurfaceAnimator.startAnimation(
window.getPendingTransaction(), mock(AnimationAdapter.class),
false /* hidden */, ANIMATION_TYPE_APP_TRANSITION);
assertEquals(0, mPolicy.getPreferredModeId(window));
assertEquals(0, mPolicy.getPreferredRefreshRate(window), FLOAT_TOLERANCE);
assertEquals(0, mPolicy.getPreferredMaxRefreshRate(window), FLOAT_TOLERANCE);
}
}

View File

@@ -231,7 +231,7 @@ public class StubTransaction extends SurfaceControl.Transaction {
@Override
public SurfaceControl.Transaction setFrameRate(SurfaceControl sc, float frameRate,
int compatibility) {
int compatibility, int changeFrameRateStrategy) {
return this;
}