Add TestApi to always select the app requested display mode
The added test API is used to ignore all votes in DisplayModeDirector app votes. This way only the app requested display mode will be picked. The API will be used for testing app mode switch requests. Bug: 159113268 Bug: 158316271 Test: m Change-Id: I257636ae2a6ed74044e71e49a99024682c3a92c5
This commit is contained in:
@@ -17,6 +17,7 @@ package android {
|
||||
field public static final String MANAGE_ROLLBACKS = "android.permission.MANAGE_ROLLBACKS";
|
||||
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";
|
||||
field public static final String READ_CELL_BROADCASTS = "android.permission.READ_CELL_BROADCASTS";
|
||||
field public static final String READ_PRIVILEGED_PHONE_STATE = "android.permission.READ_PRIVILEGED_PHONE_STATE";
|
||||
field public static final String REMOVE_TASKS = "android.permission.REMOVE_TASKS";
|
||||
@@ -1304,6 +1305,8 @@ package android.hardware.display {
|
||||
method public android.graphics.Point getStableDisplaySize();
|
||||
method public boolean isMinimalPostProcessingRequested(int);
|
||||
method @RequiresPermission(android.Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) public void setBrightnessConfiguration(android.hardware.display.BrightnessConfiguration);
|
||||
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 VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 512; // 0x200
|
||||
field public static final int VIRTUAL_DISPLAY_FLAG_TRUSTED = 1024; // 0x400
|
||||
}
|
||||
|
||||
@@ -840,6 +840,30 @@ public final class DisplayManager {
|
||||
return mGlobal.getMinimumBrightnessCurve();
|
||||
}
|
||||
|
||||
/**
|
||||
* When enabled the app requested mode is always selected regardless of user settings and
|
||||
* policies for low brightness, low battery, etc.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
@RequiresPermission(Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS)
|
||||
public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
|
||||
mGlobal.setShouldAlwaysRespectAppRequestedMode(enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether we are running in a mode which always selects the app requested display mode
|
||||
* and ignores user settings and policies for low brightness, low battery etc.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
@RequiresPermission(Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS)
|
||||
public boolean shouldAlwaysRespectAppRequestedMode() {
|
||||
return mGlobal.shouldAlwaysRespectAppRequestedMode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for changes in available display devices.
|
||||
*/
|
||||
|
||||
@@ -699,6 +699,32 @@ public final class DisplayManagerGlobal {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When enabled the app requested display resolution and refresh rate is always selected
|
||||
* in DisplayModeDirector regardless of user settings and policies for low brightness, low
|
||||
* battery etc.
|
||||
*/
|
||||
public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
|
||||
try {
|
||||
mDm.setShouldAlwaysRespectAppRequestedMode(enabled);
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether DisplayModeDirector is running in a mode which always selects the app
|
||||
* requested display mode and ignores user settings and policies for low brightness, low
|
||||
* battery etc.
|
||||
*/
|
||||
public boolean shouldAlwaysRespectAppRequestedMode() {
|
||||
try {
|
||||
return mDm.shouldAlwaysRespectAppRequestedMode();
|
||||
} catch (RemoteException ex) {
|
||||
throw ex.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
private final class DisplayManagerCallback extends IDisplayManagerCallback.Stub {
|
||||
@Override
|
||||
public void onDisplayEvent(int displayId, int event) {
|
||||
|
||||
@@ -128,4 +128,10 @@ interface IDisplayManager {
|
||||
// The wide gamut color space is returned from composition pipeline
|
||||
// based on hardware capability.
|
||||
int getPreferredWideGamutColorSpaceId();
|
||||
|
||||
// When enabled the app requested display resolution and refresh rate is always selected
|
||||
// in DisplayModeDirector regardless of user settings and policies for low brightness, low
|
||||
// battery etc.
|
||||
void setShouldAlwaysRespectAppRequestedMode(boolean enabled);
|
||||
boolean shouldAlwaysRespectAppRequestedMode();
|
||||
}
|
||||
|
||||
@@ -3910,6 +3910,14 @@
|
||||
<permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"
|
||||
android:protectionLevel="signature" />
|
||||
|
||||
<!-- Allows an application to override the display mode requests
|
||||
so the app requested mode will be selected and user settings and display
|
||||
policies will be ignored.
|
||||
@hide
|
||||
@TestApi -->
|
||||
<permission android:name="android.permission.OVERRIDE_DISPLAY_MODE_REQUESTS"
|
||||
android:protectionLevel="signature" />
|
||||
|
||||
<!-- @SystemApi Allows an application to control VPN.
|
||||
<p>Not for use by third-party applications.</p>
|
||||
@hide -->
|
||||
|
||||
@@ -323,6 +323,9 @@
|
||||
<!-- Permissions required for CTS test - AdbManagerTest -->
|
||||
<uses-permission android:name="android.permission.MANAGE_DEBUGGING" />
|
||||
|
||||
<!-- Permission needed for CTS test - DisplayTest -->
|
||||
<uses-permission android:name="android.permission.OVERRIDE_DISPLAY_MODE_REQUESTS" />
|
||||
|
||||
<application android:label="@string/app_label"
|
||||
android:theme="@android:style/Theme.DeviceDefault.DayNight"
|
||||
android:defaultToDeviceProtectedStorage="true"
|
||||
|
||||
@@ -1179,6 +1179,15 @@ public final class DisplayManagerService extends SystemService {
|
||||
return mWideColorSpace.getId();
|
||||
}
|
||||
|
||||
void setShouldAlwaysRespectAppRequestedModeInternal(boolean enabled) {
|
||||
mDisplayModeDirector.setShouldAlwaysRespectAppRequestedMode(enabled);
|
||||
}
|
||||
|
||||
|
||||
boolean shouldAlwaysRespectAppRequestedModeInternal() {
|
||||
return mDisplayModeDirector.shouldAlwaysRespectAppRequestedMode();
|
||||
}
|
||||
|
||||
private void setBrightnessConfigurationForUserInternal(
|
||||
@Nullable BrightnessConfiguration c, @UserIdInt int userId,
|
||||
@Nullable String packageName) {
|
||||
@@ -2463,6 +2472,32 @@ public final class DisplayManagerService extends SystemService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
|
||||
"Permission required to override display mode requests.");
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
setShouldAlwaysRespectAppRequestedModeInternal(enabled);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // Binder call
|
||||
public boolean shouldAlwaysRespectAppRequestedMode() {
|
||||
mContext.enforceCallingOrSelfPermission(
|
||||
Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS,
|
||||
"Permission required to override display mode requests.");
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return shouldAlwaysRespectAppRequestedModeInternal();
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean validatePackageName(int uid, String packageName) {
|
||||
if (packageName != null) {
|
||||
String[] packageNames = mContext.getPackageManager().getPackagesForUid(uid);
|
||||
|
||||
@@ -56,8 +56,8 @@ 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.
|
||||
* 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.
|
||||
*/
|
||||
public class DisplayModeDirector {
|
||||
private static final String TAG = "DisplayModeDirector";
|
||||
@@ -97,17 +97,20 @@ public class DisplayModeDirector {
|
||||
private final DeviceConfigDisplaySettings mDeviceConfigDisplaySettings;
|
||||
private DesiredDisplayModeSpecsListener mDesiredDisplayModeSpecsListener;
|
||||
|
||||
private boolean mAlwaysRespectAppRequest;
|
||||
|
||||
public DisplayModeDirector(@NonNull Context context, @NonNull Handler handler) {
|
||||
mContext = context;
|
||||
mHandler = new DisplayModeDirectorHandler(handler.getLooper());
|
||||
mVotesByDisplay = new SparseArray<>();
|
||||
mSupportedModesByDisplay = new SparseArray<>();
|
||||
mDefaultModeByDisplay = new SparseArray<>();
|
||||
mDefaultModeByDisplay = new SparseArray<>();
|
||||
mAppRequestObserver = new AppRequestObserver();
|
||||
mSettingsObserver = new SettingsObserver(context, handler);
|
||||
mDisplayObserver = new DisplayObserver(context, handler);
|
||||
mBrightnessObserver = new BrightnessObserver(context, handler);
|
||||
mDeviceConfigDisplaySettings = new DeviceConfigDisplaySettings();
|
||||
mAlwaysRespectAppRequest = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,7 +130,6 @@ public class DisplayModeDirector {
|
||||
// notify them to pick up our newly initialized state.
|
||||
notifyDesiredDisplayModeSpecsChangedLocked();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@@ -173,9 +175,14 @@ public class DisplayModeDirector {
|
||||
// VoteSummary is returned as an output param to cut down a bit on the number of temporary
|
||||
// objects.
|
||||
private void summarizeVotes(
|
||||
SparseArray<Vote> votes, int lowestConsideredPriority, /*out*/ VoteSummary summary) {
|
||||
SparseArray<Vote> votes,
|
||||
int lowestConsideredPriority,
|
||||
int highestConsideredPriority,
|
||||
/*out*/ VoteSummary summary) {
|
||||
summary.reset();
|
||||
for (int priority = Vote.MAX_PRIORITY; priority >= lowestConsideredPriority; priority--) {
|
||||
for (int priority = highestConsideredPriority;
|
||||
priority >= lowestConsideredPriority;
|
||||
priority--) {
|
||||
Vote vote = votes.get(priority);
|
||||
if (vote == null) {
|
||||
continue;
|
||||
@@ -217,8 +224,16 @@ public class DisplayModeDirector {
|
||||
int[] availableModes = new int[]{defaultMode.getModeId()};
|
||||
VoteSummary primarySummary = new VoteSummary();
|
||||
int lowestConsideredPriority = Vote.MIN_PRIORITY;
|
||||
while (lowestConsideredPriority <= Vote.MAX_PRIORITY) {
|
||||
summarizeVotes(votes, lowestConsideredPriority, primarySummary);
|
||||
int highestConsideredPriority = Vote.MAX_PRIORITY;
|
||||
|
||||
if (mAlwaysRespectAppRequest) {
|
||||
lowestConsideredPriority = Vote.PRIORITY_APP_REQUEST_REFRESH_RATE;
|
||||
highestConsideredPriority = Vote.PRIORITY_APP_REQUEST_SIZE;
|
||||
}
|
||||
|
||||
while (lowestConsideredPriority <= highestConsideredPriority) {
|
||||
summarizeVotes(
|
||||
votes, lowestConsideredPriority, highestConsideredPriority, primarySummary);
|
||||
|
||||
// If we don't have anything specifying the width / height of the display, just use
|
||||
// the default width and height. We don't want these switching out from underneath
|
||||
@@ -261,7 +276,10 @@ public class DisplayModeDirector {
|
||||
|
||||
VoteSummary appRequestSummary = new VoteSummary();
|
||||
summarizeVotes(
|
||||
votes, Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF, appRequestSummary);
|
||||
votes,
|
||||
Vote.APP_REQUEST_REFRESH_RATE_RANGE_PRIORITY_CUTOFF,
|
||||
Vote.MAX_PRIORITY,
|
||||
appRequestSummary);
|
||||
appRequestSummary.minRefreshRate =
|
||||
Math.min(appRequestSummary.minRefreshRate, primarySummary.minRefreshRate);
|
||||
appRequestSummary.maxRefreshRate =
|
||||
@@ -338,8 +356,7 @@ public class DisplayModeDirector {
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the desiredDisplayModeSpecsListener for changes to display mode and refresh rate
|
||||
* ranges.
|
||||
* Sets the desiredDisplayModeSpecsListener for changes to display mode and refresh rate ranges.
|
||||
*/
|
||||
public void setDesiredDisplayModeSpecsListener(
|
||||
@Nullable DesiredDisplayModeSpecsListener desiredDisplayModeSpecsListener) {
|
||||
@@ -348,6 +365,26 @@ public class DisplayModeDirector {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When enabled the app requested display mode is always selected and all
|
||||
* other votes will be ignored. This is used for testing purposes.
|
||||
*/
|
||||
public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
|
||||
synchronized (mLock) {
|
||||
mAlwaysRespectAppRequest = enabled;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether we are running in a mode which always selects the app requested display mode
|
||||
* and ignores user settings and policies for low brightness, low battery etc.
|
||||
*/
|
||||
public boolean shouldAlwaysRespectAppRequestedMode() {
|
||||
synchronized (mLock) {
|
||||
return mAlwaysRespectAppRequest;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the object's state and debug information into the given stream.
|
||||
*
|
||||
@@ -380,6 +417,7 @@ public class DisplayModeDirector {
|
||||
pw.println(" " + Vote.priorityToString(p) + " -> " + vote);
|
||||
}
|
||||
}
|
||||
pw.println(" mAlwaysRespectAppRequest: " + mAlwaysRespectAppRequest);
|
||||
mSettingsObserver.dumpLocked(pw);
|
||||
mAppRequestObserver.dumpLocked(pw);
|
||||
mBrightnessObserver.dumpLocked(pw);
|
||||
|
||||
@@ -302,4 +302,42 @@ public class DisplayModeDirectorTest {
|
||||
verifyBrightnessObserverCall(director, 90, 90, 0, 90, 90);
|
||||
verifyBrightnessObserverCall(director, 120, 90, 0, 120, 90);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVotingWithAlwaysRespectAppRequest() {
|
||||
final int displayId = 0;
|
||||
DisplayModeDirector director = createDirectorFromFpsRange(50, 90);
|
||||
SparseArray<Vote> votes = new SparseArray<>();
|
||||
SparseArray<SparseArray<Vote>> votesByDisplay = new SparseArray<>();
|
||||
votesByDisplay.put(displayId, votes);
|
||||
votes.put(Vote.PRIORITY_LOW_BRIGHTNESS, 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));
|
||||
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);
|
||||
Truth.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);
|
||||
|
||||
director.setShouldAlwaysRespectAppRequestedMode(true);
|
||||
Truth.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);
|
||||
|
||||
director.setShouldAlwaysRespectAppRequestedMode(false);
|
||||
Truth.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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user