Merge "Default resolution settings [Backend]"

This commit is contained in:
Kriti Dang
2021-09-10 07:31:02 +00:00
committed by Android (Google) Code Review
15 changed files with 372 additions and 37 deletions

View File

@@ -1180,12 +1180,15 @@ package android.hardware.display {
public final class DisplayManager {
method public boolean areUserDisabledHdrTypesAllowed();
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void clearUserPreferredDisplayMode();
method @NonNull public int[] getUserDisabledHdrTypes();
method @Nullable public android.view.Display.Mode getUserPreferredDisplayMode();
method public boolean isMinimalPostProcessingRequested(int);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setAreUserDisabledHdrTypesAllowed(boolean);
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.WRITE_SECURE_SETTINGS) public void setUserDisabledHdrTypes(@NonNull int[]);
method @RequiresPermission(android.Manifest.permission.WRITE_SECURE_SETTINGS) public void setUserPreferredDisplayMode(@NonNull android.view.Display.Mode);
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
@@ -2168,6 +2171,9 @@ package android.provider {
field public static final String OVERLAY_DISPLAY_DEVICES = "overlay_display_devices";
field public static final String SHOW_FIRST_CRASH_DIALOG = "show_first_crash_dialog";
field public static final String USER_DISABLED_HDR_FORMATS = "user_disabled_hdr_formats";
field public static final String USER_PREFERRED_REFRESH_RATE = "user_preferred_refresh_rate";
field public static final String USER_PREFERRED_RESOLUTION_HEIGHT = "user_preferred_resolution_height";
field public static final String USER_PREFERRED_RESOLUTION_WIDTH = "user_preferred_resolution_width";
field public static final String USE_OPEN_WIFI_PACKAGE = "use_open_wifi_package";
}
@@ -2735,6 +2741,7 @@ package android.view {
}
public final class Display {
method @NonNull public android.view.Display.Mode getDefaultMode();
method @NonNull public int[] getReportedHdrTypes();
method @NonNull public android.graphics.ColorSpace[] getSupportedWideColorGamut();
method public int getType();
@@ -2748,6 +2755,11 @@ package android.view {
field public static final int TYPE_WIFI = 3; // 0x3
}
public static final class Display.Mode implements android.os.Parcelable {
ctor public Display.Mode(int, int, float);
method public boolean matches(int, int, float);
}
public class FocusFinder {
method public static void sort(android.view.View[], int, int, android.view.ViewGroup, boolean);
}

View File

@@ -1112,6 +1112,44 @@ public final class DisplayManager {
return mGlobal.getMinimumBrightnessCurve();
}
/**
* Sets the default display mode, according to the refresh rate and the resolution chosen by the
* user.
*
* @hide
*/
@TestApi
@RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
public void setUserPreferredDisplayMode(@NonNull Display.Mode mode) {
// Create a new object containing default values for the unused fields like mode ID and
// alternative refresh rates.
Display.Mode preferredMode = new Display.Mode(mode.getPhysicalWidth(),
mode.getPhysicalHeight(), mode.getRefreshRate());
mGlobal.setUserPreferredDisplayMode(preferredMode);
}
/**
* Removes the user preferred display mode.
*
* @hide
*/
@TestApi
@RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS)
public void clearUserPreferredDisplayMode() {
mGlobal.setUserPreferredDisplayMode(null);
}
/**
* Returns the user preferred display mode.
*
* @hide
*/
@TestApi
@Nullable
public Display.Mode getUserPreferredDisplayMode() {
return mGlobal.getUserPreferredDisplayMode();
}
/**
* When enabled the app requested mode is always selected regardless of user settings and
* policies for low brightness, low battery, etc.

View File

@@ -876,6 +876,29 @@ public final class DisplayManagerGlobal {
}
}
/**
* Sets the default display mode, according to the refresh rate and the resolution chosen by the
* user.
*/
public void setUserPreferredDisplayMode(Display.Mode mode) {
try {
mDm.setUserPreferredDisplayMode(mode);
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
/**
* Returns the user preferred display mode.
*/
public Display.Mode getUserPreferredDisplayMode() {
try {
return mDm.getUserPreferredDisplayMode();
} catch (RemoteException ex) {
throw ex.rethrowFromSystemServer();
}
}
/**
* 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

View File

@@ -27,6 +27,7 @@ import android.hardware.display.VirtualDisplayConfig;
import android.hardware.display.WifiDisplay;
import android.hardware.display.WifiDisplayStatus;
import android.media.projection.IMediaProjection;
import android.view.Display.Mode;
import android.view.DisplayInfo;
import android.view.Surface;
@@ -162,6 +163,11 @@ interface IDisplayManager {
// based on hardware capability.
int getPreferredWideGamutColorSpaceId();
// Sets the user preferred display mode.
// Requires WRITE_SECURE_SETTINGS permission.
void setUserPreferredDisplayMode(in Mode mode);
Mode getUserPreferredDisplayMode();
// 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.

View File

@@ -14603,6 +14603,38 @@ public final class Settings {
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
public static final int HEADS_UP_ON = 1;
/**
* The refresh rate chosen by the user.
*
* @hide
*/
@TestApi
@Readable
@SuppressLint("NoSettingsProvider")
public static final String USER_PREFERRED_REFRESH_RATE = "user_preferred_refresh_rate";
/**
* The resolution height chosen by the user.
*
* @hide
*/
@TestApi
@Readable
@SuppressLint("NoSettingsProvider")
public static final String USER_PREFERRED_RESOLUTION_HEIGHT =
"user_preferred_resolution_height";
/**
* The resolution width chosen by the user.
*
* @hide
*/
@TestApi
@Readable
@SuppressLint("NoSettingsProvider")
public static final String USER_PREFERRED_RESOLUTION_WIDTH =
"user_preferred_resolution_width";
/**
* The name of the device
*/

View File

@@ -999,6 +999,18 @@ public final class Display {
}
}
/**
* Returns the default mode of the display.
* @hide
*/
@TestApi
public @NonNull Mode getDefaultMode() {
synchronized (mLock) {
updateDisplayInfoLocked();
return mDisplayInfo.getDefaultMode();
}
}
/**
* Gets the supported modes of this display.
*/
@@ -1699,6 +1711,11 @@ public final class Display {
*/
public static final Mode[] EMPTY_ARRAY = new Mode[0];
/**
* @hide
*/
public static final int INVALID_MODE_ID = -1;
private final int mModeId;
private final int mWidth;
private final int mHeight;
@@ -1706,6 +1723,14 @@ public final class Display {
@NonNull
private final float[] mAlternativeRefreshRates;
/**
* @hide
*/
@TestApi
public Mode(int width, int height, float refreshRate) {
this(INVALID_MODE_ID, width, height, refreshRate, new float[0]);
}
/**
* @hide
*/
@@ -1804,6 +1829,7 @@ public final class Display {
*
* @hide
*/
@TestApi
public boolean matches(int width, int height, float refreshRate) {
return mWidth == width &&
mHeight == height &&

View File

@@ -1820,11 +1820,6 @@ public final class SurfaceControl implements Parcelable {
* @hide
*/
public static final class DisplayMode {
/**
* Invalid display config id.
*/
public static final int INVALID_DISPLAY_MODE_ID = -1;
public int id;
public int width;
public int height;

View File

@@ -81,6 +81,9 @@ public class GlobalSettings {
Settings.Global.POWER_BUTTON_LONG_PRESS,
Settings.Global.AUTOMATIC_POWER_SAVE_MODE,
Settings.Global.ADVANCED_BATTERY_USAGE_AMOUNT,
Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS
Settings.Global.POWER_BUTTON_LONG_PRESS_DURATION_MS,
Settings.Global.USER_PREFERRED_REFRESH_RATE,
Settings.Global.USER_PREFERRED_RESOLUTION_HEIGHT,
Settings.Global.USER_PREFERRED_RESOLUTION_WIDTH,
};
}

View File

@@ -21,6 +21,7 @@ import static android.provider.settings.validators.SettingsValidators.ANY_INTEGE
import static android.provider.settings.validators.SettingsValidators.ANY_STRING_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.BOOLEAN_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.NONE_NEGATIVE_LONG_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_FLOAT_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.NON_NEGATIVE_INTEGER_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.PACKAGE_NAME_VALIDATOR;
import static android.provider.settings.validators.SettingsValidators.PERCENTAGE_INTEGER_VALIDATOR;
@@ -321,6 +322,9 @@ public class GlobalSettingsValidators {
VALIDATORS.put(Global.Wearable.COMBINED_LOCATION_ENABLED, BOOLEAN_VALIDATOR);
VALIDATORS.put(Global.Wearable.WRIST_ORIENTATION_MODE,
new DiscreteValueValidator(new String[] {"0", "1", "2", "3"}));
VALIDATORS.put(Global.USER_PREFERRED_REFRESH_RATE, NON_NEGATIVE_FLOAT_VALIDATOR);
VALIDATORS.put(Global.USER_PREFERRED_RESOLUTION_HEIGHT, ANY_INTEGER_VALIDATOR);
VALIDATORS.put(Global.USER_PREFERRED_RESOLUTION_WIDTH, ANY_INTEGER_VALIDATOR);
}
}

View File

@@ -74,6 +74,20 @@ public class SettingsValidators {
}
};
public static final Validator NON_NEGATIVE_FLOAT_VALIDATOR = new Validator() {
@Override
public boolean validate(@Nullable String value) {
if (value == null) {
return true;
}
try {
return Float.parseFloat(value) >= 0.0f;
} catch (NumberFormatException e) {
return false;
}
}
};
public static final Validator URI_VALIDATOR = new Validator() {
@Override
public boolean validate(@Nullable String value) {

View File

@@ -205,6 +205,13 @@ abstract class DisplayDevice {
public void setDesiredDisplayModeSpecsLocked(
DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {}
/**
* Sets the user preferred display mode. Removes the user preferred display mode and sets
* default display mode as the mode chosen by HAL, if 'mode' is null
* Returns true if the mode set by user is supported by the display.
*/
public void setUserPreferredDisplayModeLocked(Display.Mode mode) { }
/**
* Sets the requested color mode.
*/

View File

@@ -130,6 +130,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicLong;
@@ -213,6 +214,9 @@ public final class DisplayManagerService extends SystemService {
private int[] mUserDisabledHdrTypes = {};
private boolean mAreUserDisabledHdrTypesAllowed = true;
// Display mode chosen by user.
private Display.Mode mUserPreferredMode;
// The synchronization root for the display manager.
// This lock guards most of the display manager's state.
// NOTE: This is synchronized on while holding WindowManagerService.mWindowMap so never call
@@ -581,6 +585,7 @@ public final class DisplayManagerService extends SystemService {
updateSettingsLocked();
updateUserDisabledHdrTypesFromSettingsLocked();
updateUserPreferredDisplayModeSettingsLocked();
}
mDisplayModeDirector.setDesiredDisplayModeSpecsListener(
@@ -795,9 +800,8 @@ public final class DisplayManagerService extends SystemService {
mUserDisabledHdrTypes[i] = Integer.parseInt(userDisabledHdrTypeStrings[i]);
}
} catch (NumberFormatException e) {
Slog.e(TAG,
"Failed to parse USER_DISABLED_HDR_FORMATS. "
+ "Clearing the setting.", e);
Slog.e(TAG, "Failed to parse USER_DISABLED_HDR_FORMATS. "
+ "Clearing the setting.", e);
clearUserDisabledHdrTypesLocked();
}
} else {
@@ -813,6 +817,17 @@ public final class DisplayManagerService extends SystemService {
}
}
private void updateUserPreferredDisplayModeSettingsLocked() {
final float refreshRate = Settings.Global.getFloat(mContext.getContentResolver(),
Settings.Global.USER_PREFERRED_REFRESH_RATE, 0.0f);
final int height = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.USER_PREFERRED_RESOLUTION_HEIGHT, -1);
final int width = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.USER_PREFERRED_RESOLUTION_WIDTH, -1);
Display.Mode mode = new Display.Mode(height, width, refreshRate);
mUserPreferredMode = isResolutionAndRefreshRateValid(mode) ? mode : null;
}
private DisplayInfo getDisplayInfoForFrameRateOverride(DisplayEventReceiver.FrameRateOverride[]
frameRateOverrides, DisplayInfo info, int callingUid) {
float frameRateHz = 0;
@@ -1259,6 +1274,9 @@ public final class DisplayManagerService extends SystemService {
recordStableDisplayStatsIfNeededLocked(display);
recordTopInsetLocked(display);
}
if (mUserPreferredMode != null) {
device.setUserPreferredDisplayModeLocked(mUserPreferredMode);
}
addDisplayPowerControllerLocked(display);
mDisplayStates.append(displayId, Display.STATE_UNKNOWN);
@@ -1429,6 +1447,39 @@ public final class DisplayManagerService extends SystemService {
return mWideColorSpace.getId();
}
void setUserPreferredDisplayModeInternal(Display.Mode mode) {
synchronized (mSyncRoot) {
if (Objects.equals(mUserPreferredMode, mode)) {
return;
}
if (mode != null && !isResolutionAndRefreshRateValid(mode)) {
throw new IllegalArgumentException("width, height and refresh rate of mode should "
+ "be greater than 0");
}
mUserPreferredMode = mode;
final int resolutionHeight = mode == null ? -1 : mode.getPhysicalHeight();
final int resolutionWidth = mode == null ? -1 : mode.getPhysicalWidth();
final float refreshRate = mode == null ? 0.0f : mode.getRefreshRate();
Settings.Global.putFloat(mContext.getContentResolver(),
Settings.Global.USER_PREFERRED_REFRESH_RATE, refreshRate);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.USER_PREFERRED_RESOLUTION_HEIGHT, resolutionHeight);
Settings.Global.putInt(mContext.getContentResolver(),
Settings.Global.USER_PREFERRED_RESOLUTION_WIDTH, resolutionWidth);
mDisplayDeviceRepo.forEachLocked((DisplayDevice device) -> {
device.setUserPreferredDisplayModeLocked(mode);
});
}
}
private Display.Mode getUserPreferredDisplayModeInternal() {
synchronized (mSyncRoot) {
return mUserPreferredMode;
}
}
void setShouldAlwaysRespectAppRequestedModeInternal(boolean enabled) {
mDisplayModeDirector.setShouldAlwaysRespectAppRequestedMode(enabled);
}
@@ -2019,6 +2070,10 @@ public final class DisplayManagerService extends SystemService {
pw.println(" mStableDisplaySize=" + mStableDisplaySize);
pw.println(" mMinimumBrightnessCurve=" + mMinimumBrightnessCurve);
if (mUserPreferredMode != null) {
pw.println(mUserPreferredMode.toString());
}
pw.println();
if (!mAreUserDisabledHdrTypesAllowed) {
pw.println(" mUserDisabledHdrTypes: size=" + mUserDisabledHdrTypes.length);
@@ -2097,6 +2152,11 @@ public final class DisplayManagerService extends SystemService {
return floatArray;
}
private static boolean isResolutionAndRefreshRateValid(Display.Mode mode) {
return mode.getPhysicalWidth() > 0 && mode.getPhysicalHeight() > 0
&& mode.getRefreshRate() > 0.0f;
}
/**
* This is the object that everything in the display manager locks on.
* We make it an inner class within the {@link DisplayManagerService} to so that it is
@@ -3083,6 +3143,29 @@ public final class DisplayManagerService extends SystemService {
}
}
@Override // Binder call
public void setUserPreferredDisplayMode(Display.Mode mode) {
mContext.enforceCallingOrSelfPermission(
Manifest.permission.WRITE_SECURE_SETTINGS,
"Permission required to set the user preferred display mode.");
final long token = Binder.clearCallingIdentity();
try {
setUserPreferredDisplayModeInternal(mode);
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override // Binder call
public Display.Mode getUserPreferredDisplayMode() {
final long token = Binder.clearCallingIdentity();
try {
return getUserPreferredDisplayModeInternal();
} finally {
Binder.restoreCallingIdentity(token);
}
}
@Override // Binder call
public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) {
mContext.enforceCallingOrSelfPermission(

View File

@@ -97,8 +97,6 @@ public class DisplayModeDirector {
// specific display.
private static final int GLOBAL_ID = -1;
private static final int INVALID_DISPLAY_MODE_ID = -1;
private static final float FLOAT_TOLERANCE = RefreshRateRange.FLOAT_TOLERANCE;
private final Object mLock = new Object();

View File

@@ -16,6 +16,8 @@
package com.android.server.display;
import static android.view.Display.Mode.INVALID_MODE_ID;
import android.app.ActivityThread;
import android.content.Context;
import android.content.res.Resources;
@@ -65,8 +67,6 @@ final class LocalDisplayAdapter extends DisplayAdapter {
private static final String PROPERTY_EMULATOR_CIRCULAR = "ro.emulator.circular";
private static final int NO_DISPLAY_MODE_ID = 0;
private final LongSparseArray<LocalDisplayDevice> mDevices = new LongSparseArray<>();
private final Injector mInjector;
@@ -191,9 +191,11 @@ final class LocalDisplayAdapter extends DisplayAdapter {
// This is only set in the runnable returned from requestDisplayStateLocked.
private float mBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
private float mSdrBrightnessState = PowerManager.BRIGHTNESS_INVALID_FLOAT;
private int mDefaultModeId;
private int mDefaultModeId = INVALID_MODE_ID;
private int mDefaultModeGroup;
private int mActiveModeId;
private int mUserPreferredModeId = INVALID_MODE_ID;
private Display.Mode mUserPreferredMode;
private int mActiveModeId = INVALID_MODE_ID;
private DisplayModeDirector.DesiredDisplayModeSpecs mDisplayModeSpecs =
new DisplayModeDirector.DesiredDisplayModeSpecs();
private boolean mDisplayModeSpecsInvalid;
@@ -323,7 +325,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
// Check whether SurfaceFlinger or the display device changed the active mode out from
// under us.
if (mActiveModeId != NO_DISPLAY_MODE_ID
if (mActiveModeId != INVALID_MODE_ID
&& mActiveModeId != activeRecord.mMode.getModeId()) {
Slog.d(TAG, "The active mode was changed from SurfaceFlinger or the display"
+ " device to " + activeRecord.mMode);
@@ -334,12 +336,12 @@ final class LocalDisplayAdapter extends DisplayAdapter {
// Check whether surface flinger spontaneously changed display config specs out from
// under us. If so, schedule a traversal to reapply our display config specs.
if (mDisplayModeSpecs.baseModeId != NO_DISPLAY_MODE_ID) {
if (mDisplayModeSpecs.baseModeId != INVALID_MODE_ID) {
int activeBaseMode = findMatchingModeIdLocked(modeSpecs.defaultMode);
// If we can't map the defaultMode index to a mode, then the physical display
// modes must have changed, and the code below for handling changes to the
// list of available modes will take care of updating display mode specs.
if (activeBaseMode == NO_DISPLAY_MODE_ID
if (activeBaseMode == INVALID_MODE_ID
|| mDisplayModeSpecs.baseModeId != activeBaseMode
|| mDisplayModeSpecs.primaryRefreshRateRange.min
!= modeSpecs.primaryRefreshRateMin
@@ -366,7 +368,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
}
// For a new display, we need to initialize the default mode ID.
if (mDefaultModeId == NO_DISPLAY_MODE_ID) {
if (mDefaultModeId == INVALID_MODE_ID) {
mDefaultModeId = activeRecord.mMode.getModeId();
mDefaultModeGroup = mActiveSfDisplayMode.group;
} else if (modesAdded && activeModeChanged) {
@@ -383,7 +385,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
// Determine whether the display mode specs' base mode is still there.
if (mSupportedModes.indexOfKey(mDisplayModeSpecs.baseModeId) < 0) {
if (mDisplayModeSpecs.baseModeId != NO_DISPLAY_MODE_ID) {
if (mDisplayModeSpecs.baseModeId != INVALID_MODE_ID) {
Slog.w(TAG,
"DisplayModeSpecs base mode no longer available, using currently"
+ " active mode.");
@@ -392,13 +394,17 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mDisplayModeSpecsInvalid = true;
}
if (mUserPreferredMode != null) {
mUserPreferredModeId = findUserPreferredModeIdLocked(mUserPreferredMode);
}
// Determine whether the active mode is still there.
if (mSupportedModes.indexOfKey(mActiveModeId) < 0) {
if (mActiveModeId != NO_DISPLAY_MODE_ID) {
if (mActiveModeId != INVALID_MODE_ID) {
Slog.w(TAG, "Active display mode no longer available, reverting to default"
+ " mode.");
}
mActiveModeId = mDefaultModeId;
mActiveModeId = getPreferredModeId();
}
// Schedule traversals so that we apply pending changes.
@@ -414,6 +420,12 @@ final class LocalDisplayAdapter extends DisplayAdapter {
return mDisplayDeviceConfig;
}
private int getPreferredModeId() {
return mUserPreferredModeId != INVALID_MODE_ID
? mUserPreferredModeId
: mDefaultModeId;
}
private void loadDisplayDeviceConfig() {
// Load display device config
final Context context = getOverlayContext();
@@ -561,7 +573,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
mInfo.width = mActiveSfDisplayMode.width;
mInfo.height = mActiveSfDisplayMode.height;
mInfo.modeId = mActiveModeId;
mInfo.defaultModeId = mDefaultModeId;
mInfo.defaultModeId = getPreferredModeId();
mInfo.supportedModes = getDisplayModes(mSupportedModes);
mInfo.colorMode = mActiveColorMode;
mInfo.allmSupported = mAllmSupported;
@@ -822,6 +834,17 @@ final class LocalDisplayAdapter extends DisplayAdapter {
return null;
}
@Override
public void setUserPreferredDisplayModeLocked(Display.Mode mode) {
final int oldModeId = getPreferredModeId();
mUserPreferredMode = mode;
mUserPreferredModeId = findUserPreferredModeIdLocked(mode);
if (oldModeId != getPreferredModeId()) {
updateDeviceInfoLocked();
}
}
@Override
public void setRequestedColorModeLocked(int colorMode) {
requestColorModeLocked(colorMode);
@@ -903,7 +926,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
}
mActiveSfDisplayMode = getModeById(mSfDisplayModes, activeSfModeId);
mActiveModeId = findMatchingModeIdLocked(activeSfModeId);
if (mActiveModeId == NO_DISPLAY_MODE_ID) {
if (mActiveModeId == INVALID_MODE_ID) {
Slog.w(TAG, "In unknown mode after setting allowed modes"
+ ", activeModeId=" + activeSfModeId);
}
@@ -988,6 +1011,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
pw.println("mActiveModeId=" + mActiveModeId);
pw.println("mActiveColorMode=" + mActiveColorMode);
pw.println("mDefaultModeId=" + mDefaultModeId);
pw.println("mUserPreferredModeId=" + mUserPreferredModeId);
pw.println("mState=" + Display.stateToString(mState));
pw.println("mBrightnessState=" + mBrightnessState);
pw.println("mBacklightAdapter=" + mBacklightAdapter);
@@ -1010,13 +1034,12 @@ final class LocalDisplayAdapter extends DisplayAdapter {
}
private int findDisplayModeIdLocked(int modeId, int modeGroup) {
int matchingModeId = SurfaceControl.DisplayMode.INVALID_DISPLAY_MODE_ID;
int matchingModeId = INVALID_MODE_ID;
DisplayModeRecord record = mSupportedModes.get(modeId);
if (record != null) {
for (SurfaceControl.DisplayMode mode : mSfDisplayModes) {
if (record.hasMatchingMode(mode)) {
if (matchingModeId
== SurfaceControl.DisplayMode.INVALID_DISPLAY_MODE_ID) {
if (matchingModeId == INVALID_MODE_ID) {
matchingModeId = mode.id;
}
@@ -1030,11 +1053,25 @@ final class LocalDisplayAdapter extends DisplayAdapter {
return matchingModeId;
}
private int findUserPreferredModeIdLocked(Display.Mode userPreferredMode) {
if (userPreferredMode != null) {
for (int i = 0; i < mSupportedModes.size(); i++) {
Display.Mode supportedMode = mSupportedModes.valueAt(i).mMode;
if (userPreferredMode.matches(supportedMode.getPhysicalWidth(),
supportedMode.getPhysicalHeight(),
supportedMode.getRefreshRate())) {
return supportedMode.getModeId();
}
}
}
return INVALID_MODE_ID;
}
private int findMatchingModeIdLocked(int sfModeId) {
SurfaceControl.DisplayMode mode = getModeById(mSfDisplayModes, sfModeId);
if (mode == null) {
Slog.e(TAG, "Invalid display mode ID " + sfModeId);
return NO_DISPLAY_MODE_ID;
return INVALID_MODE_ID;
}
for (int i = 0; i < mSupportedModes.size(); i++) {
DisplayModeRecord record = mSupportedModes.valueAt(i);
@@ -1042,7 +1079,7 @@ final class LocalDisplayAdapter extends DisplayAdapter {
return record.mMode.getModeId();
}
}
return NO_DISPLAY_MODE_ID;
return INVALID_MODE_ID;
}
private void updateDeviceInfoLocked() {

View File

@@ -335,6 +335,62 @@ public class LocalDisplayAdapterTest {
});
}
@Test
public void testAfterDisplayChange_DefaultDisplayModeIsUpdated() throws Exception {
SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(0, 1920, 1080, 60f);
SurfaceControl.DisplayMode[] modes =
new SurfaceControl.DisplayMode[]{displayMode};
FakeDisplay display = new FakeDisplay(PORT_A, modes, 0);
setUpDisplay(display);
updateAvailableDisplays();
mAdapter.registerLocked();
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
assertThat(mListener.addedDisplays.size()).isEqualTo(1);
assertThat(mListener.changedDisplays).isEmpty();
DisplayDeviceInfo displayDeviceInfo = mListener.addedDisplays.get(
0).getDisplayDeviceInfoLocked();
assertThat(displayDeviceInfo.supportedModes.length).isEqualTo(modes.length);
assertModeIsSupported(displayDeviceInfo.supportedModes, displayMode);
Display.Mode defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
assertThat(matches(defaultMode, displayMode)).isTrue();
// Set the display mode to an unsupported mode
SurfaceControl.DisplayMode displayMode2 = createFakeDisplayMode(1, 1920, 1080, 120f);
mListener.addedDisplays.get(0).setUserPreferredDisplayModeLocked(
new Display.Mode(displayMode2.width, displayMode2.height,
displayMode2.refreshRate));
updateAvailableDisplays();
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
assertThat(matches(defaultMode, displayMode2)).isFalse();
// Change the display
modes = new SurfaceControl.DisplayMode[]{displayMode, displayMode2};
display.dynamicInfo.supportedDisplayModes = modes;
setUpDisplay(display);
mInjector.getTransmitter().sendHotplug(display, /* connected */ true);
waitForHandlerToComplete(mHandler, HANDLER_WAIT_MS);
assertTrue(mListener.traversalRequested);
assertThat(mListener.addedDisplays.size()).isEqualTo(1);
assertThat(mListener.changedDisplays.size()).isEqualTo(1);
DisplayDevice displayDevice = mListener.changedDisplays.get(0);
displayDevice.applyPendingDisplayDeviceInfoChangesLocked();
displayDeviceInfo = mListener.addedDisplays.get(0).getDisplayDeviceInfoLocked();
assertThat(displayDeviceInfo.supportedModes.length).isEqualTo(modes.length);
assertModeIsSupported(displayDeviceInfo.supportedModes, displayMode);
assertModeIsSupported(displayDeviceInfo.supportedModes, displayMode2);
defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
assertThat(matches(defaultMode, displayMode2)).isTrue();
}
@Test
public void testAfterDisplayChange_DisplayModesAreUpdated() throws Exception {
SurfaceControl.DisplayMode displayMode = createFakeDisplayMode(0, 1920, 1080, 60f);
@@ -356,12 +412,10 @@ public class LocalDisplayAdapterTest {
assertModeIsSupported(displayDeviceInfo.supportedModes, displayMode);
Display.Mode defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
assertThat(defaultMode.matches(displayMode.width, displayMode.height,
displayMode.refreshRate)).isTrue();
assertThat(matches(defaultMode, displayMode)).isTrue();
Display.Mode activeMode = getModeById(displayDeviceInfo, displayDeviceInfo.modeId);
assertThat(activeMode.matches(displayMode.width, displayMode.height,
displayMode.refreshRate)).isTrue();
assertThat(matches(activeMode, displayMode)).isTrue();
// Change the display
SurfaceControl.DisplayMode addedDisplayInfo = createFakeDisplayMode(1, 3840, 2160, 60f);
@@ -385,12 +439,10 @@ public class LocalDisplayAdapterTest {
assertModeIsSupported(displayDeviceInfo.supportedModes, addedDisplayInfo);
activeMode = getModeById(displayDeviceInfo, displayDeviceInfo.modeId);
assertThat(activeMode.matches(addedDisplayInfo.width, addedDisplayInfo.height,
addedDisplayInfo.refreshRate)).isTrue();
assertThat(matches(activeMode, addedDisplayInfo)).isTrue();
defaultMode = getModeById(displayDeviceInfo, displayDeviceInfo.defaultModeId);
assertThat(defaultMode.matches(addedDisplayInfo.width, addedDisplayInfo.height,
addedDisplayInfo.refreshRate)).isTrue();
assertThat(matches(defaultMode, addedDisplayInfo)).isTrue();
}
@Test
@@ -918,4 +970,9 @@ public class LocalDisplayAdapterTest {
});
return mockArray;
}
private boolean matches(Display.Mode a, SurfaceControl.DisplayMode b) {
return a.getPhysicalWidth() == b.width && a.getPhysicalHeight() == b.height
&& Float.floatToIntBits(a.getRefreshRate()) == Float.floatToIntBits(b.refreshRate);
}
}