Merge "Default resolution settings [Backend]"
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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 &&
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user