Loading core/java/android/view/SurfaceControl.java +15 −0 Original line number Diff line number Diff line Loading @@ -122,6 +122,8 @@ public final class SurfaceControl implements Parcelable { private static native void nativeSetColor(long transactionObj, long nativeObject, float[] color); private static native void nativeSetFlags(long transactionObj, long nativeObject, int flags, int mask); private static native void nativeSetFrameRateSelectionPriority(long transactionObj, long nativeObject, int priority); private static native void nativeSetWindowCrop(long transactionObj, long nativeObject, int l, int t, int r, int b); private static native void nativeSetCornerRadius(long transactionObj, long nativeObject, Loading Loading @@ -2244,6 +2246,19 @@ public final class SurfaceControl implements Parcelable { } } /** * This information is passed to SurfaceFlinger to decide which window should have a * priority when deciding about the refresh rate of the display. All windows have the * lowest priority by default. * @hide */ @NonNull public Transaction setFrameRateSelectionPriority(@NonNull SurfaceControl sc, int priority) { sc.checkNotReleased(); nativeSetFrameRateSelectionPriority(mNativeObject, sc.mNativeObject, priority); return this; } /** * Request that a given surface and it's sub-tree be shown. * Loading core/jni/android_view_SurfaceControl.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -423,6 +423,14 @@ static void nativeSetFlags(JNIEnv* env, jclass clazz, jlong transactionObj, transaction->setFlags(ctrl, flags, mask); } static void nativeSetFrameRateSelectionPriority(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, jint priority) { auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); transaction->setFrameRateSelectionPriority(ctrl, priority); } static void nativeSetTransparentRegionHint(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, jobject regionObj) { SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); Loading Loading @@ -1362,6 +1370,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetColorSpaceAgnostic }, {"nativeSetFlags", "(JJII)V", (void*)nativeSetFlags }, {"nativeSetFrameRateSelectionPriority", "(JJI)V", (void*)nativeSetFrameRateSelectionPriority }, {"nativeSetWindowCrop", "(JJIIII)V", (void*)nativeSetWindowCrop }, {"nativeSetCornerRadius", "(JJF)V", Loading services/core/java/com/android/server/wm/RefreshRatePolicy.java +45 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,27 @@ class RefreshRatePolicy { private final HighRefreshRateBlacklist mHighRefreshRateBlacklist; private final WindowManagerService mWmService; /** * The following constants represent priority of the window. SF uses this information when * deciding which window has a priority when deciding about the refresh rate of the screen. * Priority 0 is considered the highest priority. -1 means that the priority is unset. */ static final int LAYER_PRIORITY_UNSET = -1; /** Windows that are in focus and voted for the preferred mode ID have the highest priority. */ static final int LAYER_PRIORITY_FOCUSED_WITH_MODE = 0; /** * This is a default priority for all windows that are in focus, but have not requested a * specific mode ID. */ static final int LAYER_PRIORITY_FOCUSED_WITHOUT_MODE = 1; /** * Windows that are not in focus, but voted for a specific mode ID should be * acknowledged by SF. For example, there are two applications in a split screen. * One voted for a given mode ID, and the second one doesn't care. Even though the * second one might be in focus, we can honor the mode ID of the first one. */ static final int LAYER_PRIORITY_NOT_FOCUSED_WITH_MODE = 2; RefreshRatePolicy(WindowManagerService wmService, DisplayInfo displayInfo, HighRefreshRateBlacklist blacklist) { mLowRefreshRateId = findLowRefreshRateModeId(displayInfo); Loading Loading @@ -92,4 +113,28 @@ class RefreshRatePolicy { } return 0; } /** * Calculate the priority based on whether the window is in focus and whether the application * voted for a specific refresh rate. * * TODO(b/144307188): This is a very basic algorithm version. Explore other signals that might * be useful in edge cases when we are deciding which layer should get priority when deciding * about the refresh rate. */ int calculatePriority(WindowState w) { boolean isFocused = w.isFocused(); int preferredModeId = getPreferredModeId(w); if (!isFocused && preferredModeId > 0) { return LAYER_PRIORITY_NOT_FOCUSED_WITH_MODE; } if (isFocused && preferredModeId == 0) { return LAYER_PRIORITY_FOCUSED_WITHOUT_MODE; } if (isFocused && preferredModeId > 0) { return LAYER_PRIORITY_FOCUSED_WITH_MODE; } return LAYER_PRIORITY_UNSET; } } services/core/java/com/android/server/wm/WindowState.java +27 −0 Original line number Diff line number Diff line Loading @@ -656,6 +656,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f; private KeyInterceptionInfo mKeyInterceptionInfo; /** * This information is passed to SurfaceFlinger to decide which window should have a priority * when deciding about the refresh rate of the display. All windows have the lowest priority by * default. The variable is cached, so we do not send too many updates to SF. */ int mFrameRateSelectionPriority = RefreshRatePolicy.LAYER_PRIORITY_UNSET; /** * @return The insets state as requested by the client, i.e. the dispatched insets state * for which the visibilities are overridden with what the client requested. Loading Loading @@ -5165,6 +5172,24 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } /** * Notifies SF about the priority of the window, if it changed. SF then uses this information * to decide which window's desired rendering rate should have a priority when deciding about * the refresh rate of the screen. Priority * {@link RefreshRatePolicy#LAYER_PRIORITY_FOCUSED_WITH_MODE} is considered the highest. */ @VisibleForTesting void updateFrameRateSelectionPriorityIfNeeded() { final int priority = getDisplayContent().getDisplayPolicy().getRefreshRatePolicy() .calculatePriority(this); if (mFrameRateSelectionPriority != priority) { mFrameRateSelectionPriority = priority; getPendingTransaction().setFrameRateSelectionPriority(mSurfaceControl, mFrameRateSelectionPriority); } } @Override void prepareSurfaces() { final Dimmer dimmer = getDimmer(); Loading @@ -5173,6 +5198,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP applyDims(dimmer); } updateSurfacePosition(); // Send information to SufaceFlinger about the priority of the current window. updateFrameRateSelectionPriorityIfNeeded(); mWinAnimator.prepareSurfaceLocked(true); super.prepareSurfaces(); Loading services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java 0 → 100644 +161 −0 Original line number Diff line number Diff line /* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import android.platform.test.annotations.Presubmit; import org.junit.Test; import org.junit.runner.RunWith; /** * This file tests WM setting the priority on windows that is used in SF to determine at what * frame rate the Display should run. Any changes to the algorithm should be reflected in these * tests. * * Build/Install/Run: atest FrameRateSelectionPriority */ @Presubmit @RunWith(WindowTestRunner.class) public class FrameRateSelectionPriorityTests extends WindowTestsBase { @Test public void basicTest() { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); assertNotNull("Window state is created", appWindow); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority doesn't change. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); // Call the function a few times. appWindow.updateFrameRateSelectionPriorityIfNeeded(); appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Since nothing changed in the priority state, the transaction should not be updating. verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); } @Test public void testApplicationInFocusWithoutModeId() { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); assertEquals(appWindow.getDisplayContent().getDisplayPolicy().getRefreshRatePolicy() .getPreferredModeId(appWindow), 0); appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority stays MAX_VALUE. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); // Application is in focus. appWindow.mToken.mDisplayContent.mCurrentFocus = appWindow; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes to 1. assertEquals(appWindow.mFrameRateSelectionPriority, 1); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), 1); } @Test public void testApplicationInFocusWithModeId() { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); // Application is in focus. appWindow.mToken.mDisplayContent.mCurrentFocus = appWindow; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 1); // Update the mode ID to a requested number. appWindow.mAttrs.preferredDisplayModeId = 1; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 0); // Remove the mode ID request. appWindow.mAttrs.preferredDisplayModeId = 0; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 1); // Verify we called actions on Transactions correctly. verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), 0); verify(appWindow.getPendingTransaction(), times(2)).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), 1); } @Test public void testApplicationNotInFocusWithModeId() { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); final WindowState inFocusWindow = createWindow(null, TYPE_APPLICATION, "inFocus"); appWindow.mToken.mDisplayContent.mCurrentFocus = inFocusWindow; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // The window is not in focus. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); // Update the mode ID to a requested number. appWindow.mAttrs.preferredDisplayModeId = 1; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 2); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), 2); } @Test public void testApplicationNotInFocusWithoutModeId() { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); final WindowState inFocusWindow = createWindow(null, TYPE_APPLICATION, "inFocus"); appWindow.mToken.mDisplayContent.mCurrentFocus = inFocusWindow; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // The window is not in focus. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); // Make sure that the mode ID is not set. appWindow.mAttrs.preferredDisplayModeId = 0; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority doesn't change. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); } } Loading
core/java/android/view/SurfaceControl.java +15 −0 Original line number Diff line number Diff line Loading @@ -122,6 +122,8 @@ public final class SurfaceControl implements Parcelable { private static native void nativeSetColor(long transactionObj, long nativeObject, float[] color); private static native void nativeSetFlags(long transactionObj, long nativeObject, int flags, int mask); private static native void nativeSetFrameRateSelectionPriority(long transactionObj, long nativeObject, int priority); private static native void nativeSetWindowCrop(long transactionObj, long nativeObject, int l, int t, int r, int b); private static native void nativeSetCornerRadius(long transactionObj, long nativeObject, Loading Loading @@ -2244,6 +2246,19 @@ public final class SurfaceControl implements Parcelable { } } /** * This information is passed to SurfaceFlinger to decide which window should have a * priority when deciding about the refresh rate of the display. All windows have the * lowest priority by default. * @hide */ @NonNull public Transaction setFrameRateSelectionPriority(@NonNull SurfaceControl sc, int priority) { sc.checkNotReleased(); nativeSetFrameRateSelectionPriority(mNativeObject, sc.mNativeObject, priority); return this; } /** * Request that a given surface and it's sub-tree be shown. * Loading
core/jni/android_view_SurfaceControl.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -423,6 +423,14 @@ static void nativeSetFlags(JNIEnv* env, jclass clazz, jlong transactionObj, transaction->setFlags(ctrl, flags, mask); } static void nativeSetFrameRateSelectionPriority(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, jint priority) { auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj); SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); transaction->setFrameRateSelectionPriority(ctrl, priority); } static void nativeSetTransparentRegionHint(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject, jobject regionObj) { SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject); Loading Loading @@ -1362,6 +1370,8 @@ static const JNINativeMethod sSurfaceControlMethods[] = { (void*)nativeSetColorSpaceAgnostic }, {"nativeSetFlags", "(JJII)V", (void*)nativeSetFlags }, {"nativeSetFrameRateSelectionPriority", "(JJI)V", (void*)nativeSetFrameRateSelectionPriority }, {"nativeSetWindowCrop", "(JJIIII)V", (void*)nativeSetWindowCrop }, {"nativeSetCornerRadius", "(JJF)V", Loading
services/core/java/com/android/server/wm/RefreshRatePolicy.java +45 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,27 @@ class RefreshRatePolicy { private final HighRefreshRateBlacklist mHighRefreshRateBlacklist; private final WindowManagerService mWmService; /** * The following constants represent priority of the window. SF uses this information when * deciding which window has a priority when deciding about the refresh rate of the screen. * Priority 0 is considered the highest priority. -1 means that the priority is unset. */ static final int LAYER_PRIORITY_UNSET = -1; /** Windows that are in focus and voted for the preferred mode ID have the highest priority. */ static final int LAYER_PRIORITY_FOCUSED_WITH_MODE = 0; /** * This is a default priority for all windows that are in focus, but have not requested a * specific mode ID. */ static final int LAYER_PRIORITY_FOCUSED_WITHOUT_MODE = 1; /** * Windows that are not in focus, but voted for a specific mode ID should be * acknowledged by SF. For example, there are two applications in a split screen. * One voted for a given mode ID, and the second one doesn't care. Even though the * second one might be in focus, we can honor the mode ID of the first one. */ static final int LAYER_PRIORITY_NOT_FOCUSED_WITH_MODE = 2; RefreshRatePolicy(WindowManagerService wmService, DisplayInfo displayInfo, HighRefreshRateBlacklist blacklist) { mLowRefreshRateId = findLowRefreshRateModeId(displayInfo); Loading Loading @@ -92,4 +113,28 @@ class RefreshRatePolicy { } return 0; } /** * Calculate the priority based on whether the window is in focus and whether the application * voted for a specific refresh rate. * * TODO(b/144307188): This is a very basic algorithm version. Explore other signals that might * be useful in edge cases when we are deciding which layer should get priority when deciding * about the refresh rate. */ int calculatePriority(WindowState w) { boolean isFocused = w.isFocused(); int preferredModeId = getPreferredModeId(w); if (!isFocused && preferredModeId > 0) { return LAYER_PRIORITY_NOT_FOCUSED_WITH_MODE; } if (isFocused && preferredModeId == 0) { return LAYER_PRIORITY_FOCUSED_WITHOUT_MODE; } if (isFocused && preferredModeId > 0) { return LAYER_PRIORITY_FOCUSED_WITH_MODE; } return LAYER_PRIORITY_UNSET; } }
services/core/java/com/android/server/wm/WindowState.java +27 −0 Original line number Diff line number Diff line Loading @@ -656,6 +656,13 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP private static final float DEFAULT_DIM_AMOUNT_DEAD_WINDOW = 0.5f; private KeyInterceptionInfo mKeyInterceptionInfo; /** * This information is passed to SurfaceFlinger to decide which window should have a priority * when deciding about the refresh rate of the display. All windows have the lowest priority by * default. The variable is cached, so we do not send too many updates to SF. */ int mFrameRateSelectionPriority = RefreshRatePolicy.LAYER_PRIORITY_UNSET; /** * @return The insets state as requested by the client, i.e. the dispatched insets state * for which the visibilities are overridden with what the client requested. Loading Loading @@ -5165,6 +5172,24 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP } } /** * Notifies SF about the priority of the window, if it changed. SF then uses this information * to decide which window's desired rendering rate should have a priority when deciding about * the refresh rate of the screen. Priority * {@link RefreshRatePolicy#LAYER_PRIORITY_FOCUSED_WITH_MODE} is considered the highest. */ @VisibleForTesting void updateFrameRateSelectionPriorityIfNeeded() { final int priority = getDisplayContent().getDisplayPolicy().getRefreshRatePolicy() .calculatePriority(this); if (mFrameRateSelectionPriority != priority) { mFrameRateSelectionPriority = priority; getPendingTransaction().setFrameRateSelectionPriority(mSurfaceControl, mFrameRateSelectionPriority); } } @Override void prepareSurfaces() { final Dimmer dimmer = getDimmer(); Loading @@ -5173,6 +5198,8 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP applyDims(dimmer); } updateSurfacePosition(); // Send information to SufaceFlinger about the priority of the current window. updateFrameRateSelectionPriorityIfNeeded(); mWinAnimator.prepareSurfaceLocked(true); super.prepareSurfaces(); Loading
services/tests/wmtests/src/com/android/server/wm/FrameRateSelectionPriorityTests.java 0 → 100644 +161 −0 Original line number Diff line number Diff line /* * Copyright 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.server.wm; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION; import static com.android.dx.mockito.inline.extended.ExtendedMockito.never; import static com.android.dx.mockito.inline.extended.ExtendedMockito.times; import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import android.platform.test.annotations.Presubmit; import org.junit.Test; import org.junit.runner.RunWith; /** * This file tests WM setting the priority on windows that is used in SF to determine at what * frame rate the Display should run. Any changes to the algorithm should be reflected in these * tests. * * Build/Install/Run: atest FrameRateSelectionPriority */ @Presubmit @RunWith(WindowTestRunner.class) public class FrameRateSelectionPriorityTests extends WindowTestsBase { @Test public void basicTest() { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); assertNotNull("Window state is created", appWindow); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority doesn't change. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); // Call the function a few times. appWindow.updateFrameRateSelectionPriorityIfNeeded(); appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Since nothing changed in the priority state, the transaction should not be updating. verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); } @Test public void testApplicationInFocusWithoutModeId() { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); assertEquals(appWindow.getDisplayContent().getDisplayPolicy().getRefreshRatePolicy() .getPreferredModeId(appWindow), 0); appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority stays MAX_VALUE. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); // Application is in focus. appWindow.mToken.mDisplayContent.mCurrentFocus = appWindow; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes to 1. assertEquals(appWindow.mFrameRateSelectionPriority, 1); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), 1); } @Test public void testApplicationInFocusWithModeId() { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); // Application is in focus. appWindow.mToken.mDisplayContent.mCurrentFocus = appWindow; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 1); // Update the mode ID to a requested number. appWindow.mAttrs.preferredDisplayModeId = 1; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 0); // Remove the mode ID request. appWindow.mAttrs.preferredDisplayModeId = 0; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 1); // Verify we called actions on Transactions correctly. verify(appWindow.getPendingTransaction(), never()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), 0); verify(appWindow.getPendingTransaction(), times(2)).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), 1); } @Test public void testApplicationNotInFocusWithModeId() { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); final WindowState inFocusWindow = createWindow(null, TYPE_APPLICATION, "inFocus"); appWindow.mToken.mDisplayContent.mCurrentFocus = inFocusWindow; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // The window is not in focus. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); // Update the mode ID to a requested number. appWindow.mAttrs.preferredDisplayModeId = 1; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority changes. assertEquals(appWindow.mFrameRateSelectionPriority, 2); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), 2); } @Test public void testApplicationNotInFocusWithoutModeId() { final WindowState appWindow = createWindow(null, TYPE_APPLICATION, "appWindow"); assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); final WindowState inFocusWindow = createWindow(null, TYPE_APPLICATION, "inFocus"); appWindow.mToken.mDisplayContent.mCurrentFocus = inFocusWindow; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // The window is not in focus. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); // Make sure that the mode ID is not set. appWindow.mAttrs.preferredDisplayModeId = 0; appWindow.updateFrameRateSelectionPriorityIfNeeded(); // Priority doesn't change. assertEquals(appWindow.mFrameRateSelectionPriority, RefreshRatePolicy.LAYER_PRIORITY_UNSET); verify(appWindow.getPendingTransaction()).setFrameRateSelectionPriority( appWindow.getSurfaceControl(), RefreshRatePolicy.LAYER_PRIORITY_UNSET); } }