Loading api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -52693,6 +52693,7 @@ package android.view { public static final class Display.Mode implements android.os.Parcelable { method public int describeContents(); method @NonNull public float[] getAlternativeRefreshRates(); method public int getModeId(); method public int getPhysicalHeight(); method public int getPhysicalWidth(); core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -50798,6 +50798,7 @@ package android.view { public static final class Display.Mode implements android.os.Parcelable { method public int describeContents(); method @NonNull public float[] getAlternativeRefreshRates(); method public int getModeId(); method public int getPhysicalHeight(); method public int getPhysicalWidth(); core/java/android/view/Display.java +42 −2 Original line number Diff line number Diff line Loading @@ -1405,16 +1405,29 @@ public final class Display { private final int mWidth; private final int mHeight; private final float mRefreshRate; @NonNull private final float[] mAlternativeRefreshRates; /** * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Mode(int modeId, int width, int height, float refreshRate) { this(modeId, width, height, refreshRate, new float[0]); } /** * @hide */ public Mode(int modeId, int width, int height, float refreshRate, float[] alternativeRefreshRates) { mModeId = modeId; mWidth = width; mHeight = height; mRefreshRate = refreshRate; mAlternativeRefreshRates = Arrays.copyOf(alternativeRefreshRates, alternativeRefreshRates.length); Arrays.sort(mAlternativeRefreshRates); } /** Loading Loading @@ -1463,6 +1476,28 @@ public final class Display { return mRefreshRate; } /** * Returns an array of refresh rates which can be switched to seamlessly. * <p> * A seamless switch is one without visual interruptions, such as a black screen for * a second or two. * <p> * Presence in this list does not guarantee a switch will occur to the desired * refresh rate, but rather, if a switch does occur to a refresh rate in this list, * it is guaranteed to be seamless. * <p> * The binary relation "refresh rate X is alternative to Y" is non-reflexive, * symmetric and transitive. For example the mode 1920x1080 60Hz, will never have an * alternative refresh rate of 60Hz. If 1920x1080 60Hz has an alternative of 50Hz * then 1920x1080 50Hz will have alternative refresh rate of 60Hz. If 1920x1080 60Hz * has an alternative of 50Hz and 1920x1080 50Hz has an alternative of 24Hz, then 1920x1080 * 60Hz will also have an alternative of 24Hz. */ @NonNull public float[] getAlternativeRefreshRates() { return mAlternativeRefreshRates; } /** * Returns {@code true} if this mode matches the given parameters. * Loading @@ -1483,7 +1518,8 @@ public final class Display { return false; } Mode that = (Mode) other; return mModeId == that.mModeId && matches(that.mWidth, that.mHeight, that.mRefreshRate); return mModeId == that.mModeId && matches(that.mWidth, that.mHeight, that.mRefreshRate) && Arrays.equals(mAlternativeRefreshRates, that.mAlternativeRefreshRates); } @Override Loading @@ -1493,6 +1529,7 @@ public final class Display { hash = hash * 17 + mWidth; hash = hash * 17 + mHeight; hash = hash * 17 + Float.floatToIntBits(mRefreshRate); hash = hash * 17 + Arrays.hashCode(mAlternativeRefreshRates); return hash; } Loading @@ -1503,6 +1540,8 @@ public final class Display { .append(", width=").append(mWidth) .append(", height=").append(mHeight) .append(", fps=").append(mRefreshRate) .append(", alternativeRefreshRates=") .append(Arrays.toString(mAlternativeRefreshRates)) .append("}") .toString(); } Loading @@ -1513,7 +1552,7 @@ public final class Display { } private Mode(Parcel in) { this(in.readInt(), in.readInt(), in.readInt(), in.readFloat()); this(in.readInt(), in.readInt(), in.readInt(), in.readFloat(), in.createFloatArray()); } @Override Loading @@ -1522,6 +1561,7 @@ public final class Display { out.writeInt(mWidth); out.writeInt(mHeight); out.writeFloat(mRefreshRate); out.writeFloatArray(mAlternativeRefreshRates); } @SuppressWarnings("hiding") Loading services/core/java/com/android/server/display/DisplayAdapter.java +7 −2 Original line number Diff line number Diff line Loading @@ -120,8 +120,13 @@ abstract class DisplayAdapter { } public static Display.Mode createMode(int width, int height, float refreshRate) { return new Display.Mode( NEXT_DISPLAY_MODE_ID.getAndIncrement(), width, height, refreshRate); return createMode(width, height, refreshRate, new float[0]); } public static Display.Mode createMode(int width, int height, float refreshRate, float[] alternativeRefreshRates) { return new Display.Mode(NEXT_DISPLAY_MODE_ID.getAndIncrement(), width, height, refreshRate, alternativeRefreshRates); } public interface Listener { Loading services/core/java/com/android/server/display/LocalDisplayAdapter.java +44 −8 Original line number Diff line number Diff line Loading @@ -266,12 +266,27 @@ final class LocalDisplayAdapter extends DisplayAdapter { boolean modesAdded = false; for (int i = 0; i < configs.length; i++) { SurfaceControl.DisplayConfig config = configs[i]; List<Float> alternativeRefreshRates = new ArrayList<>(); for (int j = 0; j < configs.length; j++) { SurfaceControl.DisplayConfig other = configs[j]; boolean isAlternative = j != i && other.width == config.width && other.height == config.height && other.refreshRate != config.refreshRate && other.configGroup == config.configGroup; if (isAlternative) { alternativeRefreshRates.add(configs[j].refreshRate); } } Collections.sort(alternativeRefreshRates); // First, check to see if we've already added a matching mode. Since not all // configuration options are exposed via Display.Mode, it's possible that we have // multiple DisplayConfigs that would generate the same Display.Mode. boolean existingMode = false; for (int j = 0; j < records.size(); j++) { if (records.get(j).hasMatchingMode(config)) { for (DisplayModeRecord record : records) { if (record.hasMatchingMode(config) && refreshRatesEquals(alternativeRefreshRates, record.mMode.getAlternativeRefreshRates())) { existingMode = true; break; } Loading @@ -282,9 +297,13 @@ final class LocalDisplayAdapter extends DisplayAdapter { // If we haven't already added a mode for this configuration to the new set of // supported modes then check to see if we have one in the prior set of supported // modes to reuse. DisplayModeRecord record = findDisplayModeRecord(config); DisplayModeRecord record = findDisplayModeRecord(config, alternativeRefreshRates); if (record == null) { record = new DisplayModeRecord(config); float[] alternativeRates = new float[alternativeRefreshRates.size()]; for (int j = 0; j < alternativeRates.length; j++) { alternativeRates[j] = alternativeRefreshRates.get(j); } record = new DisplayModeRecord(config, alternativeRates); modesAdded = true; } records.add(record); Loading Loading @@ -495,16 +514,31 @@ final class LocalDisplayAdapter extends DisplayAdapter { return true; } private DisplayModeRecord findDisplayModeRecord(SurfaceControl.DisplayConfig config) { private DisplayModeRecord findDisplayModeRecord(SurfaceControl.DisplayConfig config, List<Float> alternativeRefreshRates) { for (int i = 0; i < mSupportedModes.size(); i++) { DisplayModeRecord record = mSupportedModes.valueAt(i); if (record.hasMatchingMode(config)) { if (record.hasMatchingMode(config) && refreshRatesEquals(alternativeRefreshRates, record.mMode.getAlternativeRefreshRates())) { return record; } } return null; } private boolean refreshRatesEquals(List<Float> list, float[] array) { if (list.size() != array.length) { return false; } for (int i = 0; i < list.size(); i++) { if (Float.floatToIntBits(list.get(i)) != Float.floatToIntBits(array[i])) { return false; } } return true; } @Override public void applyPendingDisplayDeviceInfoChangesLocked() { if (mHavePendingChanges) { Loading Loading @@ -1032,8 +1066,10 @@ final class LocalDisplayAdapter extends DisplayAdapter { private static final class DisplayModeRecord { public final Display.Mode mMode; DisplayModeRecord(SurfaceControl.DisplayConfig config) { mMode = createMode(config.width, config.height, config.refreshRate); DisplayModeRecord(SurfaceControl.DisplayConfig config, float[] alternativeRefreshRates) { mMode = createMode(config.width, config.height, config.refreshRate, alternativeRefreshRates); } /** Loading Loading
api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -52693,6 +52693,7 @@ package android.view { public static final class Display.Mode implements android.os.Parcelable { method public int describeContents(); method @NonNull public float[] getAlternativeRefreshRates(); method public int getModeId(); method public int getPhysicalHeight(); method public int getPhysicalWidth();
core/api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -50798,6 +50798,7 @@ package android.view { public static final class Display.Mode implements android.os.Parcelable { method public int describeContents(); method @NonNull public float[] getAlternativeRefreshRates(); method public int getModeId(); method public int getPhysicalHeight(); method public int getPhysicalWidth();
core/java/android/view/Display.java +42 −2 Original line number Diff line number Diff line Loading @@ -1405,16 +1405,29 @@ public final class Display { private final int mWidth; private final int mHeight; private final float mRefreshRate; @NonNull private final float[] mAlternativeRefreshRates; /** * @hide */ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) public Mode(int modeId, int width, int height, float refreshRate) { this(modeId, width, height, refreshRate, new float[0]); } /** * @hide */ public Mode(int modeId, int width, int height, float refreshRate, float[] alternativeRefreshRates) { mModeId = modeId; mWidth = width; mHeight = height; mRefreshRate = refreshRate; mAlternativeRefreshRates = Arrays.copyOf(alternativeRefreshRates, alternativeRefreshRates.length); Arrays.sort(mAlternativeRefreshRates); } /** Loading Loading @@ -1463,6 +1476,28 @@ public final class Display { return mRefreshRate; } /** * Returns an array of refresh rates which can be switched to seamlessly. * <p> * A seamless switch is one without visual interruptions, such as a black screen for * a second or two. * <p> * Presence in this list does not guarantee a switch will occur to the desired * refresh rate, but rather, if a switch does occur to a refresh rate in this list, * it is guaranteed to be seamless. * <p> * The binary relation "refresh rate X is alternative to Y" is non-reflexive, * symmetric and transitive. For example the mode 1920x1080 60Hz, will never have an * alternative refresh rate of 60Hz. If 1920x1080 60Hz has an alternative of 50Hz * then 1920x1080 50Hz will have alternative refresh rate of 60Hz. If 1920x1080 60Hz * has an alternative of 50Hz and 1920x1080 50Hz has an alternative of 24Hz, then 1920x1080 * 60Hz will also have an alternative of 24Hz. */ @NonNull public float[] getAlternativeRefreshRates() { return mAlternativeRefreshRates; } /** * Returns {@code true} if this mode matches the given parameters. * Loading @@ -1483,7 +1518,8 @@ public final class Display { return false; } Mode that = (Mode) other; return mModeId == that.mModeId && matches(that.mWidth, that.mHeight, that.mRefreshRate); return mModeId == that.mModeId && matches(that.mWidth, that.mHeight, that.mRefreshRate) && Arrays.equals(mAlternativeRefreshRates, that.mAlternativeRefreshRates); } @Override Loading @@ -1493,6 +1529,7 @@ public final class Display { hash = hash * 17 + mWidth; hash = hash * 17 + mHeight; hash = hash * 17 + Float.floatToIntBits(mRefreshRate); hash = hash * 17 + Arrays.hashCode(mAlternativeRefreshRates); return hash; } Loading @@ -1503,6 +1540,8 @@ public final class Display { .append(", width=").append(mWidth) .append(", height=").append(mHeight) .append(", fps=").append(mRefreshRate) .append(", alternativeRefreshRates=") .append(Arrays.toString(mAlternativeRefreshRates)) .append("}") .toString(); } Loading @@ -1513,7 +1552,7 @@ public final class Display { } private Mode(Parcel in) { this(in.readInt(), in.readInt(), in.readInt(), in.readFloat()); this(in.readInt(), in.readInt(), in.readInt(), in.readFloat(), in.createFloatArray()); } @Override Loading @@ -1522,6 +1561,7 @@ public final class Display { out.writeInt(mWidth); out.writeInt(mHeight); out.writeFloat(mRefreshRate); out.writeFloatArray(mAlternativeRefreshRates); } @SuppressWarnings("hiding") Loading
services/core/java/com/android/server/display/DisplayAdapter.java +7 −2 Original line number Diff line number Diff line Loading @@ -120,8 +120,13 @@ abstract class DisplayAdapter { } public static Display.Mode createMode(int width, int height, float refreshRate) { return new Display.Mode( NEXT_DISPLAY_MODE_ID.getAndIncrement(), width, height, refreshRate); return createMode(width, height, refreshRate, new float[0]); } public static Display.Mode createMode(int width, int height, float refreshRate, float[] alternativeRefreshRates) { return new Display.Mode(NEXT_DISPLAY_MODE_ID.getAndIncrement(), width, height, refreshRate, alternativeRefreshRates); } public interface Listener { Loading
services/core/java/com/android/server/display/LocalDisplayAdapter.java +44 −8 Original line number Diff line number Diff line Loading @@ -266,12 +266,27 @@ final class LocalDisplayAdapter extends DisplayAdapter { boolean modesAdded = false; for (int i = 0; i < configs.length; i++) { SurfaceControl.DisplayConfig config = configs[i]; List<Float> alternativeRefreshRates = new ArrayList<>(); for (int j = 0; j < configs.length; j++) { SurfaceControl.DisplayConfig other = configs[j]; boolean isAlternative = j != i && other.width == config.width && other.height == config.height && other.refreshRate != config.refreshRate && other.configGroup == config.configGroup; if (isAlternative) { alternativeRefreshRates.add(configs[j].refreshRate); } } Collections.sort(alternativeRefreshRates); // First, check to see if we've already added a matching mode. Since not all // configuration options are exposed via Display.Mode, it's possible that we have // multiple DisplayConfigs that would generate the same Display.Mode. boolean existingMode = false; for (int j = 0; j < records.size(); j++) { if (records.get(j).hasMatchingMode(config)) { for (DisplayModeRecord record : records) { if (record.hasMatchingMode(config) && refreshRatesEquals(alternativeRefreshRates, record.mMode.getAlternativeRefreshRates())) { existingMode = true; break; } Loading @@ -282,9 +297,13 @@ final class LocalDisplayAdapter extends DisplayAdapter { // If we haven't already added a mode for this configuration to the new set of // supported modes then check to see if we have one in the prior set of supported // modes to reuse. DisplayModeRecord record = findDisplayModeRecord(config); DisplayModeRecord record = findDisplayModeRecord(config, alternativeRefreshRates); if (record == null) { record = new DisplayModeRecord(config); float[] alternativeRates = new float[alternativeRefreshRates.size()]; for (int j = 0; j < alternativeRates.length; j++) { alternativeRates[j] = alternativeRefreshRates.get(j); } record = new DisplayModeRecord(config, alternativeRates); modesAdded = true; } records.add(record); Loading Loading @@ -495,16 +514,31 @@ final class LocalDisplayAdapter extends DisplayAdapter { return true; } private DisplayModeRecord findDisplayModeRecord(SurfaceControl.DisplayConfig config) { private DisplayModeRecord findDisplayModeRecord(SurfaceControl.DisplayConfig config, List<Float> alternativeRefreshRates) { for (int i = 0; i < mSupportedModes.size(); i++) { DisplayModeRecord record = mSupportedModes.valueAt(i); if (record.hasMatchingMode(config)) { if (record.hasMatchingMode(config) && refreshRatesEquals(alternativeRefreshRates, record.mMode.getAlternativeRefreshRates())) { return record; } } return null; } private boolean refreshRatesEquals(List<Float> list, float[] array) { if (list.size() != array.length) { return false; } for (int i = 0; i < list.size(); i++) { if (Float.floatToIntBits(list.get(i)) != Float.floatToIntBits(array[i])) { return false; } } return true; } @Override public void applyPendingDisplayDeviceInfoChangesLocked() { if (mHavePendingChanges) { Loading Loading @@ -1032,8 +1066,10 @@ final class LocalDisplayAdapter extends DisplayAdapter { private static final class DisplayModeRecord { public final Display.Mode mMode; DisplayModeRecord(SurfaceControl.DisplayConfig config) { mMode = createMode(config.width, config.height, config.refreshRate); DisplayModeRecord(SurfaceControl.DisplayConfig config, float[] alternativeRefreshRates) { mMode = createMode(config.width, config.height, config.refreshRate, alternativeRefreshRates); } /** Loading