Loading services/core/java/com/android/server/wm/DisplayContent.java +5 −1 Original line number Diff line number Diff line Loading @@ -2116,6 +2116,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp w.seamlesslyRotateIfAllowed(transaction, oldRotation, rotation, rotateSeamlessly); }, true /* traverseTopToBottom */); mPinnedTaskController.startSeamlessRotationIfNeeded(transaction, oldRotation, rotation); if (!mDisplayRotation.hasSeamlessRotatingWindow()) { // Make sure DisplayRotation#isRotatingSeamlessly() will return false. mDisplayRotation.cancelSeamlessRotation(); } } mWmService.mDisplayManagerInternal.performTraversal(transaction); Loading Loading @@ -4824,7 +4828,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mInsetsStateController.getImeSourceProvider().checkShowImePostLayout(); mLastHasContent = mTmpApplySurfaceChangesTransactionState.displayHasContent; if (!mWmService.mDisplayFrozen) { if (!mWmService.mDisplayFrozen && !mDisplayRotation.isRotatingSeamlessly()) { mWmService.mDisplayManagerInternal.setDisplayProperties(mDisplayId, mLastHasContent, mTmpApplySurfaceChangesTransactionState.preferredRefreshRate, Loading services/core/java/com/android/server/wm/RefreshRatePolicy.java +38 −12 Original line number Diff line number Diff line Loading @@ -53,6 +53,8 @@ class RefreshRatePolicy { } } private final DisplayInfo mDisplayInfo; private final Mode mDefaultMode; private final Mode mLowRefreshRateMode; private final PackageRefreshRate mNonHighRefreshRatePackages = new PackageRefreshRate(); private final HighRefreshRateDenylist mHighRefreshRateDenylist; Loading Loading @@ -83,7 +85,9 @@ class RefreshRatePolicy { RefreshRatePolicy(WindowManagerService wmService, DisplayInfo displayInfo, HighRefreshRateDenylist denylist) { mLowRefreshRateMode = findLowRefreshRateMode(displayInfo); mDisplayInfo = displayInfo; mDefaultMode = displayInfo.getDefaultMode(); mLowRefreshRateMode = findLowRefreshRateMode(displayInfo, mDefaultMode); mHighRefreshRateDenylist = denylist; mWmService = wmService; } Loading @@ -92,10 +96,9 @@ class RefreshRatePolicy { * Finds the mode id with the lowest refresh rate which is >= 60hz and same resolution as the * default mode. */ private Mode findLowRefreshRateMode(DisplayInfo displayInfo) { Mode mode = displayInfo.getDefaultMode(); private Mode findLowRefreshRateMode(DisplayInfo displayInfo, Mode defaultMode) { float[] refreshRates = displayInfo.getDefaultRefreshRates(); float bestRefreshRate = mode.getRefreshRate(); float bestRefreshRate = defaultMode.getRefreshRate(); mMinSupportedRefreshRate = bestRefreshRate; mMaxSupportedRefreshRate = bestRefreshRate; for (int i = refreshRates.length - 1; i >= 0; i--) { Loading @@ -121,13 +124,39 @@ class RefreshRatePolicy { } int getPreferredModeId(WindowState w) { final int preferredDisplayModeId = w.mAttrs.preferredDisplayModeId; if (preferredDisplayModeId <= 0) { // Unspecified, use default mode. return 0; } // If app is animating, it's not able to control refresh rate because we want the animation // to run in default refresh rate. // to run in default refresh rate. But if the display size of default mode is different // from the using preferred mode, then still keep the preferred mode to avoid disturbing // the animation. if (w.isAnimating(TRANSITION | PARENTS)) { Display.Mode preferredMode = null; for (Display.Mode mode : mDisplayInfo.supportedModes) { if (preferredDisplayModeId == mode.getModeId()) { preferredMode = mode; break; } } if (preferredMode != null) { final int pW = preferredMode.getPhysicalWidth(); final int pH = preferredMode.getPhysicalHeight(); if ((pW != mDefaultMode.getPhysicalWidth() || pH != mDefaultMode.getPhysicalHeight()) && pW == mDisplayInfo.getNaturalWidth() && pH == mDisplayInfo.getNaturalHeight()) { // Prefer not to change display size when animating. return preferredDisplayModeId; } } return 0; } return w.mAttrs.preferredDisplayModeId; return preferredDisplayModeId; } /** Loading Loading @@ -165,15 +194,12 @@ class RefreshRatePolicy { // of that mode id. final int preferredModeId = w.mAttrs.preferredDisplayModeId; if (preferredModeId > 0) { DisplayInfo info = w.getDisplayInfo(); if (info != null) { for (Display.Mode mode : info.supportedModes) { for (Display.Mode mode : mDisplayInfo.supportedModes) { if (preferredModeId == mode.getModeId()) { return mode.getRefreshRate(); } } } } if (w.mAttrs.preferredRefreshRate > 0) { return w.mAttrs.preferredRefreshRate; Loading services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java +10 −0 Original line number Diff line number Diff line Loading @@ -21,7 +21,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.os.Parcel; Loading Loading @@ -258,6 +260,14 @@ public class RefreshRatePolicyTest extends WindowTestsBase { assertEquals(0, mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE); // If there will be display size change when switching from preferred mode to default mode, // then keep the current preferred mode during animating. mDisplayInfo = spy(mDisplayInfo); final Mode defaultMode = new Mode(4321 /* width */, 1234 /* height */, LOW_REFRESH_RATE); doReturn(defaultMode).when(mDisplayInfo).getDefaultMode(); mPolicy = new RefreshRatePolicy(mWm, mDisplayInfo, mDenylist); assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(overrideWindow)); } @Test Loading Loading
services/core/java/com/android/server/wm/DisplayContent.java +5 −1 Original line number Diff line number Diff line Loading @@ -2116,6 +2116,10 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp w.seamlesslyRotateIfAllowed(transaction, oldRotation, rotation, rotateSeamlessly); }, true /* traverseTopToBottom */); mPinnedTaskController.startSeamlessRotationIfNeeded(transaction, oldRotation, rotation); if (!mDisplayRotation.hasSeamlessRotatingWindow()) { // Make sure DisplayRotation#isRotatingSeamlessly() will return false. mDisplayRotation.cancelSeamlessRotation(); } } mWmService.mDisplayManagerInternal.performTraversal(transaction); Loading Loading @@ -4824,7 +4828,7 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp mInsetsStateController.getImeSourceProvider().checkShowImePostLayout(); mLastHasContent = mTmpApplySurfaceChangesTransactionState.displayHasContent; if (!mWmService.mDisplayFrozen) { if (!mWmService.mDisplayFrozen && !mDisplayRotation.isRotatingSeamlessly()) { mWmService.mDisplayManagerInternal.setDisplayProperties(mDisplayId, mLastHasContent, mTmpApplySurfaceChangesTransactionState.preferredRefreshRate, Loading
services/core/java/com/android/server/wm/RefreshRatePolicy.java +38 −12 Original line number Diff line number Diff line Loading @@ -53,6 +53,8 @@ class RefreshRatePolicy { } } private final DisplayInfo mDisplayInfo; private final Mode mDefaultMode; private final Mode mLowRefreshRateMode; private final PackageRefreshRate mNonHighRefreshRatePackages = new PackageRefreshRate(); private final HighRefreshRateDenylist mHighRefreshRateDenylist; Loading Loading @@ -83,7 +85,9 @@ class RefreshRatePolicy { RefreshRatePolicy(WindowManagerService wmService, DisplayInfo displayInfo, HighRefreshRateDenylist denylist) { mLowRefreshRateMode = findLowRefreshRateMode(displayInfo); mDisplayInfo = displayInfo; mDefaultMode = displayInfo.getDefaultMode(); mLowRefreshRateMode = findLowRefreshRateMode(displayInfo, mDefaultMode); mHighRefreshRateDenylist = denylist; mWmService = wmService; } Loading @@ -92,10 +96,9 @@ class RefreshRatePolicy { * Finds the mode id with the lowest refresh rate which is >= 60hz and same resolution as the * default mode. */ private Mode findLowRefreshRateMode(DisplayInfo displayInfo) { Mode mode = displayInfo.getDefaultMode(); private Mode findLowRefreshRateMode(DisplayInfo displayInfo, Mode defaultMode) { float[] refreshRates = displayInfo.getDefaultRefreshRates(); float bestRefreshRate = mode.getRefreshRate(); float bestRefreshRate = defaultMode.getRefreshRate(); mMinSupportedRefreshRate = bestRefreshRate; mMaxSupportedRefreshRate = bestRefreshRate; for (int i = refreshRates.length - 1; i >= 0; i--) { Loading @@ -121,13 +124,39 @@ class RefreshRatePolicy { } int getPreferredModeId(WindowState w) { final int preferredDisplayModeId = w.mAttrs.preferredDisplayModeId; if (preferredDisplayModeId <= 0) { // Unspecified, use default mode. return 0; } // If app is animating, it's not able to control refresh rate because we want the animation // to run in default refresh rate. // to run in default refresh rate. But if the display size of default mode is different // from the using preferred mode, then still keep the preferred mode to avoid disturbing // the animation. if (w.isAnimating(TRANSITION | PARENTS)) { Display.Mode preferredMode = null; for (Display.Mode mode : mDisplayInfo.supportedModes) { if (preferredDisplayModeId == mode.getModeId()) { preferredMode = mode; break; } } if (preferredMode != null) { final int pW = preferredMode.getPhysicalWidth(); final int pH = preferredMode.getPhysicalHeight(); if ((pW != mDefaultMode.getPhysicalWidth() || pH != mDefaultMode.getPhysicalHeight()) && pW == mDisplayInfo.getNaturalWidth() && pH == mDisplayInfo.getNaturalHeight()) { // Prefer not to change display size when animating. return preferredDisplayModeId; } } return 0; } return w.mAttrs.preferredDisplayModeId; return preferredDisplayModeId; } /** Loading Loading @@ -165,15 +194,12 @@ class RefreshRatePolicy { // of that mode id. final int preferredModeId = w.mAttrs.preferredDisplayModeId; if (preferredModeId > 0) { DisplayInfo info = w.getDisplayInfo(); if (info != null) { for (Display.Mode mode : info.supportedModes) { for (Display.Mode mode : mDisplayInfo.supportedModes) { if (preferredModeId == mode.getModeId()) { return mode.getRefreshRate(); } } } } if (w.mAttrs.preferredRefreshRate > 0) { return w.mAttrs.preferredRefreshRate; Loading
services/tests/wmtests/src/com/android/server/wm/RefreshRatePolicyTest.java +10 −0 Original line number Diff line number Diff line Loading @@ -21,7 +21,9 @@ import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION; import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; import static org.junit.Assert.assertEquals; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.when; import android.os.Parcel; Loading Loading @@ -258,6 +260,14 @@ public class RefreshRatePolicyTest extends WindowTestsBase { assertEquals(0, mPolicy.getPreferredRefreshRate(overrideWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMinRefreshRate(overrideWindow), FLOAT_TOLERANCE); assertEquals(0, mPolicy.getPreferredMaxRefreshRate(overrideWindow), FLOAT_TOLERANCE); // If there will be display size change when switching from preferred mode to default mode, // then keep the current preferred mode during animating. mDisplayInfo = spy(mDisplayInfo); final Mode defaultMode = new Mode(4321 /* width */, 1234 /* height */, LOW_REFRESH_RATE); doReturn(defaultMode).when(mDisplayInfo).getDefaultMode(); mPolicy = new RefreshRatePolicy(mWm, mDisplayInfo, mDenylist); assertEquals(LOW_MODE_ID, mPolicy.getPreferredModeId(overrideWindow)); } @Test Loading