diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java index bbdd7d339507e..fdccfd8e2dc81 100644 --- a/core/java/android/view/SurfaceControl.java +++ b/core/java/android/view/SurfaceControl.java @@ -1897,16 +1897,23 @@ public final class SurfaceControl implements Parcelable { public float appRequestRefreshRateMin; public float appRequestRefreshRateMax; + /** + * If true this will allow switching between modes in different display configuration + * groups. This way the user may see visual interruptions when the display mode changes. + */ + public boolean allowGroupSwitching; + public DesiredDisplayConfigSpecs() {} public DesiredDisplayConfigSpecs(DesiredDisplayConfigSpecs other) { copyFrom(other); } - public DesiredDisplayConfigSpecs(int defaultConfig, float primaryRefreshRateMin, - float primaryRefreshRateMax, float appRequestRefreshRateMin, - float appRequestRefreshRateMax) { + public DesiredDisplayConfigSpecs(int defaultConfig, boolean allowGroupSwitching, + float primaryRefreshRateMin, float primaryRefreshRateMax, + float appRequestRefreshRateMin, float appRequestRefreshRateMax) { this.defaultConfig = defaultConfig; + this.allowGroupSwitching = allowGroupSwitching; this.primaryRefreshRateMin = primaryRefreshRateMin; this.primaryRefreshRateMax = primaryRefreshRateMax; this.appRequestRefreshRateMin = appRequestRefreshRateMin; diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp index a61903dcb7c83..59488c1d10ae8 100644 --- a/core/jni/android_view_SurfaceControl.cpp +++ b/core/jni/android_view_SurfaceControl.cpp @@ -196,6 +196,7 @@ static struct { jclass clazz; jmethodID ctor; jfieldID defaultConfig; + jfieldID allowGroupSwitching; jfieldID primaryRefreshRateMin; jfieldID primaryRefreshRateMax; jfieldID appRequestRefreshRateMin; @@ -998,6 +999,9 @@ static jboolean nativeSetDesiredDisplayConfigSpecs(JNIEnv* env, jclass clazz, jo jint defaultConfig = env->GetIntField(desiredDisplayConfigSpecs, gDesiredDisplayConfigSpecsClassInfo.defaultConfig); + jboolean allowGroupSwitching = + env->GetBooleanField(desiredDisplayConfigSpecs, + gDesiredDisplayConfigSpecsClassInfo.allowGroupSwitching); jfloat primaryRefreshRateMin = env->GetFloatField(desiredDisplayConfigSpecs, gDesiredDisplayConfigSpecsClassInfo.primaryRefreshRateMin); @@ -1012,6 +1016,7 @@ static jboolean nativeSetDesiredDisplayConfigSpecs(JNIEnv* env, jclass clazz, jo gDesiredDisplayConfigSpecsClassInfo.appRequestRefreshRateMax); size_t result = SurfaceComposerClient::setDesiredDisplayConfigSpecs(token, defaultConfig, + allowGroupSwitching, primaryRefreshRateMin, primaryRefreshRateMax, appRequestRefreshRateMin, @@ -1024,11 +1029,13 @@ static jobject nativeGetDesiredDisplayConfigSpecs(JNIEnv* env, jclass clazz, job if (token == nullptr) return nullptr; int32_t defaultConfig; + bool allowGroupSwitching; float primaryRefreshRateMin; float primaryRefreshRateMax; float appRequestRefreshRateMin; float appRequestRefreshRateMax; if (SurfaceComposerClient::getDesiredDisplayConfigSpecs(token, &defaultConfig, + &allowGroupSwitching, &primaryRefreshRateMin, &primaryRefreshRateMax, &appRequestRefreshRateMin, @@ -1039,8 +1046,8 @@ static jobject nativeGetDesiredDisplayConfigSpecs(JNIEnv* env, jclass clazz, job return env->NewObject(gDesiredDisplayConfigSpecsClassInfo.clazz, gDesiredDisplayConfigSpecsClassInfo.ctor, defaultConfig, - primaryRefreshRateMin, primaryRefreshRateMax, appRequestRefreshRateMin, - appRequestRefreshRateMax); + allowGroupSwitching, primaryRefreshRateMin, primaryRefreshRateMax, + appRequestRefreshRateMin, appRequestRefreshRateMax); } static jint nativeGetActiveConfig(JNIEnv* env, jclass clazz, jobject tokenObj) { @@ -1857,9 +1864,11 @@ int register_android_view_SurfaceControl(JNIEnv* env) gDesiredDisplayConfigSpecsClassInfo.clazz = MakeGlobalRefOrDie(env, desiredDisplayConfigSpecsClazz); gDesiredDisplayConfigSpecsClassInfo.ctor = - GetMethodIDOrDie(env, gDesiredDisplayConfigSpecsClassInfo.clazz, "", "(IFFFF)V"); + GetMethodIDOrDie(env, gDesiredDisplayConfigSpecsClassInfo.clazz, "", "(IZFFFF)V"); gDesiredDisplayConfigSpecsClassInfo.defaultConfig = GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "defaultConfig", "I"); + gDesiredDisplayConfigSpecsClassInfo.allowGroupSwitching = + GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "allowGroupSwitching", "Z"); gDesiredDisplayConfigSpecsClassInfo.primaryRefreshRateMin = GetFieldIDOrDie(env, desiredDisplayConfigSpecsClazz, "primaryRefreshRateMin", "F"); gDesiredDisplayConfigSpecsClassInfo.primaryRefreshRateMax = diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java index 4f5a0faee8ddc..37bf3bd008863 100644 --- a/services/core/java/com/android/server/display/DisplayModeDirector.java +++ b/services/core/java/com/android/server/display/DisplayModeDirector.java @@ -16,6 +16,7 @@ package com.android.server.display; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.ContentResolver; @@ -50,11 +51,14 @@ import com.android.server.display.utils.AmbientFilter; import com.android.server.display.utils.AmbientFilterFactory; import java.io.PrintWriter; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Objects; + /** * The DisplayModeDirector is responsible for determining what modes are allowed to be automatically * picked by the system based on system-wide and display-specific configuration. @@ -99,6 +103,29 @@ public class DisplayModeDirector { private boolean mAlwaysRespectAppRequest; + @IntDef(prefix = {"SWITCHING_TYPE_"}, value = { + SWITCHING_TYPE_NONE, + SWITCHING_TYPE_WITHIN_GROUPS, + SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface SwitchingType {} + + // No mode switching will happen. + public static final int SWITCHING_TYPE_NONE = 0; + // Allow only refresh rate switching between modes in the same configuration group. This way + // only switches without visual interruptions for the user will be allowed. + public static final int SWITCHING_TYPE_WITHIN_GROUPS = 1; + // Allow refresh rate switching between all refresh rates even if the switch with have visual + // interruptions for the user. + public static final int SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS = 2; + + /** + * The allowed refresh rate switching type. This is used by SurfaceFlinger. + */ + @SwitchingType + private int mModeSwitchingType = SWITCHING_TYPE_WITHIN_GROUPS; + public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler) { mContext = context; mHandler = new DisplayModeDirectorHandler(handler.getLooper()); @@ -291,14 +318,37 @@ public class DisplayModeDirector { appRequestSummary.maxRefreshRate)); } + // If the application requests a given mode with preferredModeId function, it will be + // stored as baseModeId. int baseModeId = defaultMode.getModeId(); if (availableModes.length > 0) { baseModeId = availableModes[0]; } - // filterModes function is going to filter the modes based on the voting system. If - // the application requests a given mode with preferredModeId function, it will be - // stored as baseModeId. + if (mModeSwitchingType == 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."); + } + float fps = baseMode.getRefreshRate(); + return new DesiredDisplayModeSpecs(baseModeId, + /*allowGroupSwitching */ false, + new RefreshRateRange(fps, fps), + new RefreshRateRange(fps, fps)); + } + + boolean allowGroupSwitching = + mModeSwitchingType == SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS; return new DesiredDisplayModeSpecs(baseModeId, + allowGroupSwitching, new RefreshRateRange( primarySummary.minRefreshRate, primarySummary.maxRefreshRate), new RefreshRateRange( @@ -385,6 +435,26 @@ public class DisplayModeDirector { } } + /** + * Sets the display mode switching type. + * @param type + */ + public void setModeSwitchingType(@SwitchingType int type) { + synchronized (mLock) { + mModeSwitchingType = type; + } + } + + /** + * Returns the display mode switching type. + */ + @SwitchingType + public int getModeSwitchingType() { + synchronized (mLock) { + return mModeSwitchingType; + } + } + /** * Print the object's state and debug information into the given stream. * @@ -417,6 +487,7 @@ public class DisplayModeDirector { pw.println(" " + Vote.priorityToString(p) + " -> " + vote); } } + pw.println(" mModeSwitchingType: " + switchingTypeToString(mModeSwitchingType)); pw.println(" mAlwaysRespectAppRequest: " + mAlwaysRespectAppRequest); mSettingsObserver.dumpLocked(pw); mAppRequestObserver.dumpLocked(pw); @@ -473,7 +544,6 @@ public class DisplayModeDirector { } private SparseArray getOrCreateVotesByDisplay(int displayId) { - int index = mVotesByDisplay.indexOfKey(displayId); if (mVotesByDisplay.indexOfKey(displayId) >= 0) { return mVotesByDisplay.get(displayId); } else { @@ -483,6 +553,19 @@ public class DisplayModeDirector { } } + private static String switchingTypeToString(@SwitchingType int type) { + switch (type) { + case SWITCHING_TYPE_NONE: + return "SWITCHING_TYPE_NONE"; + case SWITCHING_TYPE_WITHIN_GROUPS: + return "SWITCHING_TYPE_WITHIN_GROUPS"; + case SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS: + return "SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS"; + default: + return "Unknown SwitchingType " + type; + } + } + @VisibleForTesting void injectSupportedModesByDisplay(SparseArray supportedModesByDisplay) { mSupportedModesByDisplay = supportedModesByDisplay; @@ -632,18 +715,26 @@ public class DisplayModeDirector { * SurfaceControl.DesiredDisplayConfigSpecs uses, and the mode ID used here. */ public static final class DesiredDisplayModeSpecs { + /** * Base mode ID. This is what system defaults to for all other settings, or * if the refresh rate range is not available. */ public int baseModeId; + + /** + * If true this will allow switching between modes in different display configuration + * groups. This way the user may see visual interruptions when the display mode changes. + */ + public boolean allowGroupSwitching; + /** * The primary refresh rate range. */ public final RefreshRateRange primaryRefreshRateRange; /** * The app request refresh rate range. Lower priority considerations won't be included in - * this range, allowing surface flinger to consider additional refresh rates for apps that + * this range, allowing SurfaceFlinger to consider additional refresh rates for apps that * call setFrameRate(). This range will be greater than or equal to the primary refresh rate * range, never smaller. */ @@ -655,9 +746,11 @@ public class DisplayModeDirector { } public DesiredDisplayModeSpecs(int baseModeId, + boolean allowGroupSwitching, @NonNull RefreshRateRange primaryRefreshRateRange, @NonNull RefreshRateRange appRequestRefreshRateRange) { this.baseModeId = baseModeId; + this.allowGroupSwitching = allowGroupSwitching; this.primaryRefreshRateRange = primaryRefreshRateRange; this.appRequestRefreshRateRange = appRequestRefreshRateRange; } @@ -667,10 +760,12 @@ public class DisplayModeDirector { */ @Override public String toString() { - return String.format("baseModeId=%d primaryRefreshRateRange=[%.0f %.0f]" + return String.format("baseModeId=%d allowGroupSwitching=%b" + + " primaryRefreshRateRange=[%.0f %.0f]" + " appRequestRefreshRateRange=[%.0f %.0f]", - baseModeId, primaryRefreshRateRange.min, primaryRefreshRateRange.max, - appRequestRefreshRateRange.min, appRequestRefreshRateRange.max); + baseModeId, allowGroupSwitching, primaryRefreshRateRange.min, + primaryRefreshRateRange.max, appRequestRefreshRateRange.min, + appRequestRefreshRateRange.max); } /** * Checks whether the two objects have the same values. @@ -690,6 +785,9 @@ public class DisplayModeDirector { if (baseModeId != desiredDisplayModeSpecs.baseModeId) { return false; } + if (allowGroupSwitching != desiredDisplayModeSpecs.allowGroupSwitching) { + return false; + } if (!primaryRefreshRateRange.equals(desiredDisplayModeSpecs.primaryRefreshRateRange)) { return false; } @@ -702,7 +800,8 @@ public class DisplayModeDirector { @Override public int hashCode() { - return Objects.hash(baseModeId, primaryRefreshRateRange, appRequestRefreshRateRange); + return Objects.hash(baseModeId, allowGroupSwitching, primaryRefreshRateRange, + appRequestRefreshRateRange); } /** @@ -710,6 +809,7 @@ public class DisplayModeDirector { */ public void copyFrom(DesiredDisplayModeSpecs other) { baseModeId = other.baseModeId; + allowGroupSwitching = other.allowGroupSwitching; primaryRefreshRateRange.min = other.primaryRefreshRateRange.min; primaryRefreshRateRange.max = other.primaryRefreshRateRange.max; appRequestRefreshRateRange.min = other.appRequestRefreshRateRange.min; diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java index 6597aa54d66b2..31e9f237b2a74 100644 --- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java +++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java @@ -811,6 +811,7 @@ final class LocalDisplayAdapter extends DisplayAdapter { LocalDisplayDevice::setDesiredDisplayModeSpecsAsync, this, getDisplayTokenLocked(), new SurfaceControl.DesiredDisplayConfigSpecs(baseConfigId, + mDisplayModeSpecs.allowGroupSwitching, mDisplayModeSpecs.primaryRefreshRateRange.min, mDisplayModeSpecs.primaryRefreshRateRange.max, mDisplayModeSpecs.appRequestRefreshRateRange.min, diff --git a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java index 0ab15017a2b46..aa18e636be38d 100644 --- a/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/display/LocalDisplayAdapterTest.java @@ -389,7 +389,12 @@ public class LocalDisplayAdapterTest { public Display.HdrCapabilities hdrCapabilities = new Display.HdrCapabilities(new int[0], 1000, 1000, 0); public SurfaceControl.DesiredDisplayConfigSpecs desiredDisplayConfigSpecs = - new SurfaceControl.DesiredDisplayConfigSpecs(0, 60.f, 60.f, 60.f, 60.f); + new SurfaceControl.DesiredDisplayConfigSpecs(/* defaultConfig */ 0, + /* allowGroupSwitching */ false, + /* primaryRefreshRateMin */ 60.f, + /* primaryRefreshRateMax */ 60.f, + /* appRefreshRateMin */ 60.f, + /* appRefreshRateMax */60.f); private FakeDisplay(int port) { this.address = createDisplayAddress(port); diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java index b8dbd6267bc51..325ba118c7115 100644 --- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java +++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java @@ -16,6 +16,8 @@ package com.android.server.display; +import static com.google.common.truth.Truth.assertThat; + import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.verify; @@ -33,8 +35,6 @@ import com.android.server.display.DisplayModeDirector.BrightnessObserver; import com.android.server.display.DisplayModeDirector.DesiredDisplayModeSpecs; import com.android.server.display.DisplayModeDirector.Vote; -import com.google.common.truth.Truth; - import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -90,9 +90,9 @@ public class DisplayModeDirectorTest { // With no votes present, DisplayModeDirector should allow any refresh rate. DesiredDisplayModeSpecs modeSpecs = createDirectorFromFpsRange(60, 90).getDesiredDisplayModeSpecs(displayId); - Truth.assertThat(modeSpecs.baseModeId).isEqualTo(60); - Truth.assertThat(modeSpecs.primaryRefreshRateRange.min).isEqualTo(0f); - Truth.assertThat(modeSpecs.primaryRefreshRateRange.max).isEqualTo(Float.POSITIVE_INFINITY); + assertThat(modeSpecs.baseModeId).isEqualTo(60); + assertThat(modeSpecs.primaryRefreshRateRange.min).isEqualTo(0f); + assertThat(modeSpecs.primaryRefreshRateRange.max).isEqualTo(Float.POSITIVE_INFINITY); int numPriorities = DisplayModeDirector.Vote.MAX_PRIORITY - DisplayModeDirector.Vote.MIN_PRIORITY + 1; @@ -112,10 +112,10 @@ public class DisplayModeDirectorTest { votes.put(priority, Vote.forRefreshRates(minFps + i, maxFps - i)); director.injectVotesByDisplay(votesByDisplay); modeSpecs = director.getDesiredDisplayModeSpecs(displayId); - Truth.assertThat(modeSpecs.baseModeId).isEqualTo(minFps + i); - Truth.assertThat(modeSpecs.primaryRefreshRateRange.min) + assertThat(modeSpecs.baseModeId).isEqualTo(minFps + i); + assertThat(modeSpecs.primaryRefreshRateRange.min) .isEqualTo((float) (minFps + i)); - Truth.assertThat(modeSpecs.primaryRefreshRateRange.max) + assertThat(modeSpecs.primaryRefreshRateRange.max) .isEqualTo((float) (maxFps - i)); } } @@ -132,9 +132,9 @@ public class DisplayModeDirectorTest { votes.put(Vote.MIN_PRIORITY, Vote.forRefreshRates(70, 80)); director.injectVotesByDisplay(votesByDisplay); modeSpecs = director.getDesiredDisplayModeSpecs(displayId); - Truth.assertThat(modeSpecs.baseModeId).isEqualTo(70); - Truth.assertThat(modeSpecs.primaryRefreshRateRange.min).isEqualTo(70f); - Truth.assertThat(modeSpecs.primaryRefreshRateRange.max).isEqualTo(80f); + assertThat(modeSpecs.baseModeId).isEqualTo(70); + assertThat(modeSpecs.primaryRefreshRateRange.min).isEqualTo(70f); + assertThat(modeSpecs.primaryRefreshRateRange.max).isEqualTo(80f); } } @@ -153,9 +153,9 @@ public class DisplayModeDirectorTest { director.injectVotesByDisplay(votesByDisplay); DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60); - Truth.assertThat(desiredSpecs.baseModeId).isEqualTo(60); + assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60); + assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60); + assertThat(desiredSpecs.baseModeId).isEqualTo(60); } @Test @@ -172,32 +172,32 @@ public class DisplayModeDirectorTest { votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60)); director.injectVotesByDisplay(votesByDisplay); DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60); + 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(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(90, 90)); director.injectVotesByDisplay(votesByDisplay); desiredSpecs = director.getDesiredDisplayModeSpecs(displayId); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90); + 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(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60)); director.injectVotesByDisplay(votesByDisplay); desiredSpecs = director.getDesiredDisplayModeSpecs(displayId); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90); + 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(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(90, 90)); director.injectVotesByDisplay(votesByDisplay); desiredSpecs = director.getDesiredDisplayModeSpecs(displayId); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60); + assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60); + assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60); } @Test @@ -219,29 +219,29 @@ public class DisplayModeDirectorTest { votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, Vote.forRefreshRates(60, 60)); director.injectVotesByDisplay(votesByDisplay); DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60); - Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.min).isAtMost(60f); - Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f); + 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(displayId); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isAtLeast(90f); - Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.min).isAtMost(60f); - Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.max).isAtLeast(90f); + 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)); director.injectVotesByDisplay(votesByDisplay); desiredSpecs = director.getDesiredDisplayModeSpecs(displayId); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(75); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(75); - Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.min) + 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); - Truth.assertThat(desiredSpecs.appRequestRefreshRateRange.max) + assertThat(desiredSpecs.appRequestRefreshRateRange.max) .isWithin(FLOAT_TOLERANCE) .of(75); } @@ -251,10 +251,10 @@ public class DisplayModeDirectorTest { float appRequestMin, float appRequestMax) { DesiredDisplayModeSpecs specs = director.getDesiredDisplayModeSpecsWithInjectedFpsSettings( minFps, peakFps, defaultFps); - Truth.assertThat(specs.primaryRefreshRateRange.min).isEqualTo(primaryMin); - Truth.assertThat(specs.primaryRefreshRateRange.max).isEqualTo(primaryMax); - Truth.assertThat(specs.appRequestRefreshRateRange.min).isEqualTo(appRequestMin); - Truth.assertThat(specs.appRequestRefreshRateRange.max).isEqualTo(appRequestMax); + assertThat(specs.primaryRefreshRateRange.min).isEqualTo(primaryMin); + assertThat(specs.primaryRefreshRateRange.max).isEqualTo(primaryMax); + assertThat(specs.appRequestRefreshRateRange.min).isEqualTo(appRequestMin); + assertThat(specs.appRequestRefreshRateRange.max).isEqualTo(appRequestMax); } @Test @@ -318,26 +318,84 @@ public class DisplayModeDirectorTest { director.injectVotesByDisplay(votesByDisplay); - Truth.assertThat(director.shouldAlwaysRespectAppRequestedMode()).isFalse(); + assertThat(director.shouldAlwaysRespectAppRequestedMode()).isFalse(); DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60); - Truth.assertThat(desiredSpecs.baseModeId).isEqualTo(60); + assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60); + assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60); + assertThat(desiredSpecs.baseModeId).isEqualTo(60); director.setShouldAlwaysRespectAppRequestedMode(true); - Truth.assertThat(director.shouldAlwaysRespectAppRequestedMode()).isTrue(); + assertThat(director.shouldAlwaysRespectAppRequestedMode()).isTrue(); desiredSpecs = director.getDesiredDisplayModeSpecs(displayId); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90); - Truth.assertThat(desiredSpecs.baseModeId).isEqualTo(90); + assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(90); + assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(90); + assertThat(desiredSpecs.baseModeId).isEqualTo(90); director.setShouldAlwaysRespectAppRequestedMode(false); - Truth.assertThat(director.shouldAlwaysRespectAppRequestedMode()).isFalse(); + assertThat(director.shouldAlwaysRespectAppRequestedMode()).isFalse(); desiredSpecs = director.getDesiredDisplayModeSpecs(displayId); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60); - Truth.assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60); - Truth.assertThat(desiredSpecs.baseModeId).isEqualTo(60); + assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(60); + assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60); + assertThat(desiredSpecs.baseModeId).isEqualTo(60); + } + + @Test + public void testVotingWithSwitchingTypeNone() { + final int displayId = 0; + DisplayModeDirector director = createDirectorFromFpsRange(0, 90); + SparseArray votes = new SparseArray<>(); + SparseArray> votesByDisplay = new SparseArray<>(); + votesByDisplay.put(displayId, votes); + votes.put(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE, Vote.forRefreshRates(30, 90)); + votes.put(Vote.PRIORITY_LOW_POWER_MODE, Vote.forRefreshRates(0, 60)); + + + director.injectVotesByDisplay(votesByDisplay); + assertThat(director.getModeSwitchingType()) + .isNotEqualTo(DisplayModeDirector.SWITCHING_TYPE_NONE); + DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId); + + assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(30); + assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60); + assertThat(desiredSpecs.appRequestRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(0); + assertThat(desiredSpecs.appRequestRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60); + assertThat(desiredSpecs.baseModeId).isEqualTo(30); + + director.setModeSwitchingType(DisplayModeDirector.SWITCHING_TYPE_NONE); + assertThat(director.getModeSwitchingType()) + .isEqualTo(DisplayModeDirector.SWITCHING_TYPE_NONE); + + desiredSpecs = director.getDesiredDisplayModeSpecs(displayId); + assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(30); + assertThat(desiredSpecs.primaryRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(30); + assertThat(desiredSpecs.appRequestRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(30); + assertThat(desiredSpecs.appRequestRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(30); + assertThat(desiredSpecs.baseModeId).isEqualTo(30); + } + + @Test + public void testVotingWithSwitchingTypeWithinGroups() { + final int displayId = 0; + DisplayModeDirector director = createDirectorFromFpsRange(0, 90); + + director.setModeSwitchingType(DisplayModeDirector.SWITCHING_TYPE_WITHIN_GROUPS); + assertThat(director.getModeSwitchingType()) + .isEqualTo(DisplayModeDirector.SWITCHING_TYPE_WITHIN_GROUPS); + DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId); + assertThat(desiredSpecs.allowGroupSwitching).isFalse(); + } + + @Test + public void testVotingWithSwitchingTypeWithinAndAcrossGroups() { + final int displayId = 0; + DisplayModeDirector director = createDirectorFromFpsRange(0, 90); + + director.setModeSwitchingType(DisplayModeDirector.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS); + assertThat(director.getModeSwitchingType()) + .isEqualTo(DisplayModeDirector.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS); + DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId); + assertThat(desiredSpecs.allowGroupSwitching).isTrue(); } }