Merge "Add TestApi to always select the app requested display mode"
This commit is contained in:
committed by
Android (Google) Code Review
commit
768cbbd32c
@@ -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";
|
||||
@@ -1313,6 +1314,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();
|
||||
}
|
||||
|
||||
@@ -3914,6 +3914,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