Add TestApi for setRefreshRateSwitchingType
This CLs adds a test API to replicted the behaviour of the
MATCH_CONTENT_FRAME_RATE user setting. This is intended to
be used from CTS.
Bug: 157504046
Bug: 171952409
Test: atest MatchContentFrameRateTest
Change-Id: I90d9a0d019cdb908b3b13328a78fe370676ad064
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index e392ed7..51edd03 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -18,6 +18,7 @@
field public static final String MANAGE_CRATES = "android.permission.MANAGE_CRATES";
field public static final String MANAGE_NOTIFICATION_LISTENERS = "android.permission.MANAGE_NOTIFICATION_LISTENERS";
field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
+ field public static final String MODIFY_REFRESH_RATE_SWITCHING_TYPE = "android.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE";
field public static final String NETWORK_SETTINGS = "android.permission.NETWORK_SETTINGS";
field public static final String NETWORK_STACK = "android.permission.NETWORK_STACK";
field public static final String OVERRIDE_DISPLAY_MODE_REQUESTS = "android.permission.OVERRIDE_DISPLAY_MODE_REQUESTS";
@@ -743,9 +744,14 @@
}
public final class DisplayManager {
+ method @RequiresPermission(android.Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE) public int getRefreshRateSwitchingType();
method public boolean isMinimalPostProcessingRequested(int);
+ method @RequiresPermission(android.Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE) public void setRefreshRateSwitchingType(int);
method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public void setShouldAlwaysRespectAppRequestedMode(boolean);
method @RequiresPermission(android.Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) public boolean shouldAlwaysRespectAppRequestedMode();
+ field public static final int SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS = 2; // 0x2
+ field public static final int SWITCHING_TYPE_NONE = 0; // 0x0
+ field public static final int SWITCHING_TYPE_WITHIN_GROUPS = 1; // 0x1
field public static final int VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 512; // 0x200
field public static final int VIRTUAL_DISPLAY_FLAG_TRUSTED = 1024; // 0x400
}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index ca5eeb1..9bae1ff 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -19,6 +19,7 @@
import static android.view.Display.DEFAULT_DISPLAY;
import android.Manifest;
+import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -38,9 +39,12 @@
import android.view.Display;
import android.view.Surface;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
+
/**
* Manages the properties of attached displays.
*/
@@ -336,6 +340,40 @@
*/
public static final int VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP = 1 << 11;
+
+ /** @hide */
+ @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.
+ * @hide
+ */
+ @TestApi
+ 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.
+ * @hide
+ */
+ @TestApi
+ 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.
+ * @hide
+ */
+ @TestApi
+ public static final int SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS = 2;
+
+
/** @hide */
public DisplayManager(Context context) {
mContext = context;
@@ -875,6 +913,29 @@
}
/**
+ * Sets the refresh rate switching type.
+ * This matches {@link android.provider.Settings.Secure.MATCH_CONTENT_FRAME_RATE}
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE)
+ public void setRefreshRateSwitchingType(@SwitchingType int newValue) {
+ mGlobal.setRefreshRateSwitchingType(newValue);
+ }
+
+ /**
+ * Returns the refresh rate switching type.
+ *
+ * @hide
+ */
+ @TestApi
+ @RequiresPermission(Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE)
+ @SwitchingType public int getRefreshRateSwitchingType() {
+ return mGlobal.getRefreshRateSwitchingType();
+ }
+
+ /**
* Listens for changes in available display devices.
*/
public interface DisplayListener {
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 7b4889f..77ae947 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -725,6 +725,33 @@
}
}
+ /**
+ * Sets the refresh rate switching type.
+ *
+ * @hide
+ */
+ public void setRefreshRateSwitchingType(@DisplayManager.SwitchingType int newValue) {
+ try {
+ mDm.setRefreshRateSwitchingType(newValue);
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
+ /**
+ * Returns the refresh rate switching type.
+ *
+ * @hide
+ */
+ @DisplayManager.SwitchingType
+ public int getRefreshRateSwitchingType() {
+ try {
+ return mDm.getRefreshRateSwitchingType();
+ } catch (RemoteException ex) {
+ throw ex.rethrowFromSystemServer();
+ }
+ }
+
private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub {
@Override
public void onDisplayEvent(int displayId, int event) {
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index 85da642..a9f78fa 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -134,4 +134,10 @@
// battery etc.
void setShouldAlwaysRespectAppRequestedMode(boolean enabled);
boolean shouldAlwaysRespectAppRequestedMode();
+
+ // Sets the refresh rate switching type.
+ void setRefreshRateSwitchingType(int newValue);
+
+ // Returns the refresh rate switching type.
+ int getRefreshRateSwitchingType();
}
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 23e55cd..98f7255 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -4031,6 +4031,13 @@
<permission android:name="android.permission.OVERRIDE_DISPLAY_MODE_REQUESTS"
android:protectionLevel="signature" />
+ <!-- Allows an application to modify the refresh rate switching type. This
+ matches Setting.Secure.MATCH_CONTENT_FRAME_RATE.
+ @hide
+ @TestApi -->
+ <permission android:name="android.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE"
+ android:protectionLevel="signature" />
+
<!-- @SystemApi Allows an application to control VPN.
<p>Not for use by third-party applications.</p>
@hide -->
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 2e3ea24..92b1ca7 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -332,6 +332,9 @@
<!-- Permission needed for CTS test - DisplayTest -->
<uses-permission android:name="android.permission.OVERRIDE_DISPLAY_MODE_REQUESTS" />
+ <!-- Permission needed for CTS test - MatchContentFrameRateTest -->
+ <uses-permission android:name="android.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE" />
+
<!-- Permission needed for CTS test - TimeManagerTest -->
<uses-permission android:name="android.permission.MANAGE_TIME_AND_ZONE_DETECTION" />
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index 29b413d..d4a19d6 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -53,6 +53,7 @@
import android.hardware.display.BrightnessChangeEvent;
import android.hardware.display.BrightnessConfiguration;
import android.hardware.display.Curve;
+import android.hardware.display.DisplayManager;
import android.hardware.display.DisplayManagerGlobal;
import android.hardware.display.DisplayManagerInternal;
import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
@@ -1252,11 +1253,19 @@
mDisplayModeDirector.setShouldAlwaysRespectAppRequestedMode(enabled);
}
-
boolean shouldAlwaysRespectAppRequestedModeInternal() {
return mDisplayModeDirector.shouldAlwaysRespectAppRequestedMode();
}
+ void setRefreshRateSwitchingTypeInternal(@DisplayManager.SwitchingType int newValue) {
+ mDisplayModeDirector.setModeSwitchingType(newValue);
+ }
+
+ @DisplayManager.SwitchingType
+ int getRefreshRateSwitchingTypeInternal() {
+ return mDisplayModeDirector.getModeSwitchingType();
+ }
+
private void setBrightnessConfigurationForUserInternal(
@Nullable BrightnessConfiguration c, @UserIdInt int userId,
@Nullable String packageName) {
@@ -2595,6 +2604,32 @@
}
}
+ @Override // Binder call
+ public void setRefreshRateSwitchingType(int newValue) {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE,
+ "Permission required to modify refresh rate switching type.");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ setRefreshRateSwitchingTypeInternal(newValue);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
+ @Override // Binder call
+ public int getRefreshRateSwitchingType() {
+ mContext.enforceCallingOrSelfPermission(
+ Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE,
+ "Permission required read refresh rate switching type.");
+ final long token = Binder.clearCallingIdentity();
+ try {
+ return getRefreshRateSwitchingTypeInternal();
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ }
+
private boolean validatePackageName(int uid, String packageName) {
if (packageName != null) {
String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 329081a..9591894 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -16,7 +16,6 @@
package com.android.server.display;
-import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentResolver;
@@ -53,8 +52,6 @@
import com.android.server.utils.DeviceConfigInterface;
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;
@@ -110,28 +107,11 @@
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;
+ @DisplayManager.SwitchingType
+ private int mModeSwitchingType = DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS;
public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler) {
this(context, handler, new RealInjector());
@@ -337,7 +317,7 @@
if (availableModes.length > 0) {
baseModeId = availableModes[0];
}
- if (mModeSwitchingType == SWITCHING_TYPE_NONE) {
+ if (mModeSwitchingType == DisplayManager.SWITCHING_TYPE_NONE) {
Display.Mode baseMode = null;
for (Display.Mode mode : modes) {
if (mode.getModeId() == baseModeId) {
@@ -359,7 +339,7 @@
}
boolean allowGroupSwitching =
- mModeSwitchingType == SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS;
+ mModeSwitchingType == DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS;
return new DesiredDisplayModeSpecs(baseModeId,
allowGroupSwitching,
new RefreshRateRange(
@@ -450,18 +430,21 @@
/**
* Sets the display mode switching type.
- * @param type
+ * @param newType
*/
- public void setModeSwitchingType(@SwitchingType int type) {
+ public void setModeSwitchingType(@DisplayManager.SwitchingType int newType) {
synchronized (mLock) {
- mModeSwitchingType = type;
+ if (newType != mModeSwitchingType) {
+ mModeSwitchingType = newType;
+ notifyDesiredDisplayModeSpecsChangedLocked();
+ }
}
}
/**
* Returns the display mode switching type.
*/
- @SwitchingType
+ @DisplayManager.SwitchingType
public int getModeSwitchingType() {
synchronized (mLock) {
return mModeSwitchingType;
@@ -583,13 +566,13 @@
}
}
- private static String switchingTypeToString(@SwitchingType int type) {
+ private static String switchingTypeToString(@DisplayManager.SwitchingType int type) {
switch (type) {
- case SWITCHING_TYPE_NONE:
+ case DisplayManager.SWITCHING_TYPE_NONE:
return "SWITCHING_TYPE_NONE";
- case SWITCHING_TYPE_WITHIN_GROUPS:
+ case DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS:
return "SWITCHING_TYPE_WITHIN_GROUPS";
- case SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS:
+ case DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS:
return "SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS";
default:
return "Unknown SwitchingType " + type;
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 cb5ca04..603608b 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -40,6 +40,7 @@
import android.content.Context;
import android.content.ContextWrapper;
import android.database.ContentObserver;
+import android.hardware.display.DisplayManager;
import android.hardware.Sensor;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
@@ -402,7 +403,7 @@
director.injectVotesByDisplay(votesByDisplay);
assertThat(director.getModeSwitchingType())
- .isNotEqualTo(DisplayModeDirector.SWITCHING_TYPE_NONE);
+ .isNotEqualTo(DisplayManager.SWITCHING_TYPE_NONE);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(30);
@@ -411,9 +412,9 @@
assertThat(desiredSpecs.appRequestRefreshRateRange.max).isWithin(FLOAT_TOLERANCE).of(60);
assertThat(desiredSpecs.baseModeId).isEqualTo(30);
- director.setModeSwitchingType(DisplayModeDirector.SWITCHING_TYPE_NONE);
+ director.setModeSwitchingType(DisplayManager.SWITCHING_TYPE_NONE);
assertThat(director.getModeSwitchingType())
- .isEqualTo(DisplayModeDirector.SWITCHING_TYPE_NONE);
+ .isEqualTo(DisplayManager.SWITCHING_TYPE_NONE);
desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
assertThat(desiredSpecs.primaryRefreshRateRange.min).isWithin(FLOAT_TOLERANCE).of(30);
@@ -428,9 +429,9 @@
final int displayId = 0;
DisplayModeDirector director = createDirectorFromFpsRange(0, 90);
- director.setModeSwitchingType(DisplayModeDirector.SWITCHING_TYPE_WITHIN_GROUPS);
+ director.setModeSwitchingType(DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS);
assertThat(director.getModeSwitchingType())
- .isEqualTo(DisplayModeDirector.SWITCHING_TYPE_WITHIN_GROUPS);
+ .isEqualTo(DisplayManager.SWITCHING_TYPE_WITHIN_GROUPS);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
assertThat(desiredSpecs.allowGroupSwitching).isFalse();
}
@@ -440,9 +441,9 @@
final int displayId = 0;
DisplayModeDirector director = createDirectorFromFpsRange(0, 90);
- director.setModeSwitchingType(DisplayModeDirector.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS);
+ director.setModeSwitchingType(DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS);
assertThat(director.getModeSwitchingType())
- .isEqualTo(DisplayModeDirector.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS);
+ .isEqualTo(DisplayManager.SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS);
DesiredDisplayModeSpecs desiredSpecs = director.getDesiredDisplayModeSpecs(displayId);
assertThat(desiredSpecs.allowGroupSwitching).isTrue();
}