Loading libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java +37 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,26 @@ public class DesktopModeStatus { private static final boolean IS_STASHING_ENABLED = SystemProperties.getBoolean( "persist.wm.debug.desktop_stashing", false); /** * Flag to indicate whether to apply shadows to windows in desktop mode. */ private static final boolean USE_WINDOW_SHADOWS = SystemProperties.getBoolean( "persist.wm.debug.desktop_use_window_shadows", true); /** * Flag to indicate whether to apply shadows to the focused window in desktop mode. * * Note: this flag is only relevant if USE_WINDOW_SHADOWS is false. */ private static final boolean USE_WINDOW_SHADOWS_FOCUSED_WINDOW = SystemProperties.getBoolean( "persist.wm.debug.desktop_use_window_shadows_focused_window", false); /** * Flag to indicate whether to apply shadows to windows in desktop mode. */ private static final boolean USE_ROUNDED_CORNERS = SystemProperties.getBoolean( "persist.wm.debug.desktop_use_rounded_corners", true); /** * Return {@code true} is desktop windowing proto 2 is enabled */ Loading Loading @@ -81,4 +101,21 @@ public class DesktopModeStatus { public static boolean isStashingEnabled() { return IS_STASHING_ENABLED; } /** * Return whether to use window shadows. * * @param isFocusedWindow whether the window to apply shadows to is focused */ public static boolean useWindowShadow(boolean isFocusedWindow) { return USE_WINDOW_SHADOWS || (USE_WINDOW_SHADOWS_FOCUSED_WINDOW && isFocusedWindow); } /** * Return whether to use rounded corners for windows. */ public static boolean useRoundedCorners() { return USE_ROUNDED_CORNERS; } } libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +3 −0 Original line number Diff line number Diff line Loading @@ -721,6 +721,9 @@ class DesktopTasksController( finishTransaction: SurfaceControl.Transaction ) { // Add rounded corners to freeform windows if (!DesktopModeStatus.useRoundedCorners()) { return } val cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context) info.changes .filter { it.taskInfo?.windowingMode == WINDOWING_MODE_FREEFORM } Loading libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +50 −33 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ import android.view.ViewConfiguration; import android.widget.ImageButton; import android.window.WindowContainerTransaction; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.launcher3.icons.BaseIconFactory; import com.android.launcher3.icons.IconProvider; Loading Loading @@ -195,46 +196,16 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin void relayout(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT, boolean applyStartTransactionOnDraw) { final int shadowRadiusID = taskInfo.isFocused ? R.dimen.freeform_decor_shadow_focused_thickness : R.dimen.freeform_decor_shadow_unfocused_thickness; final boolean isFreeform = taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM; final boolean isDragResizeable = isFreeform && taskInfo.isResizeable; if (isHandleMenuActive()) { mHandleMenu.relayout(startT); } updateRelayoutParams(mRelayoutParams, mContext, taskInfo, applyStartTransactionOnDraw); final WindowDecorLinearLayout oldRootView = mResult.mRootView; final SurfaceControl oldDecorationSurface = mDecorationContainerSurface; final WindowContainerTransaction wct = new WindowContainerTransaction(); final int windowDecorLayoutId = getDesktopModeWindowDecorLayoutId( taskInfo.getWindowingMode()); mRelayoutParams.reset(); mRelayoutParams.mRunningTaskInfo = taskInfo; mRelayoutParams.mLayoutResId = windowDecorLayoutId; mRelayoutParams.mCaptionHeightId = getCaptionHeightId(taskInfo.getWindowingMode()); mRelayoutParams.mShadowRadiusId = shadowRadiusID; mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw; // The configuration used to lay out the window decoration. The system context's config is // used when the task density has been overridden to a custom density so that the resources // and views of the decoration aren't affected and match the rest of the System UI, if not // then just use the task's configuration. A copy is made instead of using the original // reference so that the configuration isn't mutated on config changes and diff checks can // be made in WindowDecoration#relayout using the pre/post-relayout configuration. // See b/301119301. // TODO(b/301119301): consider moving the config data needed for diffs to relayout params // instead of using a whole Configuration as a parameter. final Configuration windowDecorConfig = new Configuration(); windowDecorConfig.setTo(DesktopTasksController.isDesktopDensityOverrideSet() ? mContext.getResources().getConfiguration() // Use system context. : mTaskInfo.configuration); // Use task configuration. mRelayoutParams.mWindowDecorConfig = windowDecorConfig; mRelayoutParams.mCornerRadius = (int) ScreenDecorationsUtils.getWindowCornerRadius(mContext); relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult); // After this line, mTaskInfo is up-to-date and should be used instead of taskInfo Loading Loading @@ -273,6 +244,9 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin closeMaximizeMenu(); } final boolean isFreeform = taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM; final boolean isDragResizeable = isFreeform && taskInfo.isResizeable; if (!isDragResizeable) { if (!mTaskInfo.positionInParent.equals(mPositionInParent)) { // We still want to track caption bar's exclusion region on a non-resizeable task. Loading Loading @@ -323,6 +297,45 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin } } @VisibleForTesting static void updateRelayoutParams( RelayoutParams relayoutParams, Context context, ActivityManager.RunningTaskInfo taskInfo, boolean applyStartTransactionOnDraw) { relayoutParams.reset(); relayoutParams.mRunningTaskInfo = taskInfo; relayoutParams.mLayoutResId = getDesktopModeWindowDecorLayoutId(taskInfo.getWindowingMode()); relayoutParams.mCaptionHeightId = getCaptionHeightIdStatic(taskInfo.getWindowingMode()); if (DesktopModeStatus.useWindowShadow(/* isFocusedWindow= */ taskInfo.isFocused)) { relayoutParams.mShadowRadiusId = taskInfo.isFocused ? R.dimen.freeform_decor_shadow_focused_thickness : R.dimen.freeform_decor_shadow_unfocused_thickness; } relayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw; // The configuration used to lay out the window decoration. The system context's config is // used when the task density has been overridden to a custom density so that the resources // and views of the decoration aren't affected and match the rest of the System UI, if not // then just use the task's configuration. A copy is made instead of using the original // reference so that the configuration isn't mutated on config changes and diff checks can // be made in WindowDecoration#relayout using the pre/post-relayout configuration. // See b/301119301. // TODO(b/301119301): consider moving the config data needed for diffs to relayout params // instead of using a whole Configuration as a parameter. final Configuration windowDecorConfig = new Configuration(); windowDecorConfig.setTo(DesktopTasksController.isDesktopDensityOverrideSet() ? context.getResources().getConfiguration() // Use system context. : taskInfo.configuration); // Use task configuration. relayoutParams.mWindowDecorConfig = windowDecorConfig; if (DesktopModeStatus.useRoundedCorners()) { relayoutParams.mCornerRadius = (int) ScreenDecorationsUtils.getWindowCornerRadius(context); } } private PointF calculateMaximizeMenuPosition() { final PointF position = new PointF(); final Resources resources = mContext.getResources(); Loading Loading @@ -684,7 +697,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin super.close(); } private int getDesktopModeWindowDecorLayoutId(@WindowingMode int windowingMode) { private static int getDesktopModeWindowDecorLayoutId(@WindowingMode int windowingMode) { return windowingMode == WINDOWING_MODE_FREEFORM ? R.layout.desktop_mode_app_controls_window_decor : R.layout.desktop_mode_focused_window_decor; Loading Loading @@ -730,6 +743,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin @Override int getCaptionHeightId(@WindowingMode int windowingMode) { return getCaptionHeightIdStatic(windowingMode); } private static int getCaptionHeightIdStatic(@WindowingMode int windowingMode) { return windowingMode == WINDOWING_MODE_FULLSCREEN ? R.dimen.desktop_mode_fullscreen_decor_caption_height : R.dimen.desktop_mode_freeform_decor_caption_height; Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java +77 −0 Original line number Diff line number Diff line Loading @@ -16,16 +16,24 @@ package com.android.wm.shell.windowdecor; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.content.ComponentName; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Handler; import android.os.SystemProperties; import android.testing.AndroidTestingRunner; import android.testing.TestableContext; import android.view.Choreographer; import android.view.Display; import android.view.SurfaceControl; Loading @@ -34,14 +42,17 @@ import android.window.WindowContainerTransaction; import androidx.test.filters.SmallTest; import com.android.internal.R; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestRunningTaskInfoBuilder; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.windowdecor.WindowDecoration.RelayoutParams; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading @@ -57,6 +68,13 @@ import java.util.function.Supplier; @SmallTest @RunWith(AndroidTestingRunner.class) public class DesktopModeWindowDecorationTests extends ShellTestCase { private static final String USE_WINDOW_SHADOWS_SYSPROP_KEY = "persist.wm.debug.desktop_use_window_shadows"; private static final String FOCUSED_USE_WINDOW_SHADOWS_SYSPROP_KEY = "persist.wm.debug.desktop_use_window_shadows_focused_window"; private static final String USE_ROUNDED_CORNERS_SYSPROP_KEY = "persist.wm.debug.desktop_use_rounded_corners"; @Mock private DisplayController mMockDisplayController; @Mock Loading @@ -79,14 +97,29 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { private SurfaceControlViewHost mMockSurfaceControlViewHost; @Mock private WindowDecoration.SurfaceControlViewHostFactory mMockSurfaceControlViewHostFactory; @Mock private TypedArray mMockRoundedCornersRadiusArray; private final Configuration mConfiguration = new Configuration(); private TestableContext mTestableContext; /** Set up run before test class. */ @BeforeClass public static void setUpClass() { // Reset the sysprop settings before running the test. SystemProperties.set(USE_WINDOW_SHADOWS_SYSPROP_KEY, ""); SystemProperties.set(FOCUSED_USE_WINDOW_SHADOWS_SYSPROP_KEY, ""); SystemProperties.set(USE_ROUNDED_CORNERS_SYSPROP_KEY, ""); } @Before public void setUp() { doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory).create( any(), any(), any()); doReturn(mMockTransaction).when(mMockTransactionSupplier).get(); mTestableContext = new TestableContext(mContext); mTestableContext.ensureTestableResources(); } @Test Loading @@ -105,6 +138,50 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { } @Test public void updateRelayoutParams_noSysPropFlagsSet_windowShadowsAreEnabled() { final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); RelayoutParams relayoutParams = new RelayoutParams(); DesktopModeWindowDecoration.updateRelayoutParams( relayoutParams, mContext, taskInfo, /* applyStartTransactionOnDraw= */ true); assertThat(relayoutParams.mShadowRadiusId).isNotEqualTo(Resources.ID_NULL); } @Test public void updateRelayoutParams_noSysPropFlagsSet_roundedCornersAreEnabled() { final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); fillRoundedCornersResources(/* fillValue= */ 30); RelayoutParams relayoutParams = new RelayoutParams(); DesktopModeWindowDecoration.updateRelayoutParams( relayoutParams, mTestableContext, taskInfo, /* applyStartTransactionOnDraw= */ true); assertThat(relayoutParams.mCornerRadius).isGreaterThan(0); } private void fillRoundedCornersResources(int fillValue) { when(mMockRoundedCornersRadiusArray.getDimensionPixelSize(anyInt(), anyInt())) .thenReturn(fillValue); mTestableContext.getOrCreateTestableResources().addOverride( R.array.config_roundedCornerRadiusArray, mMockRoundedCornersRadiusArray); mTestableContext.getOrCreateTestableResources().addOverride( R.dimen.rounded_corner_radius, fillValue); mTestableContext.getOrCreateTestableResources().addOverride( R.array.config_roundedCornerTopRadiusArray, mMockRoundedCornersRadiusArray); mTestableContext.getOrCreateTestableResources().addOverride( R.dimen.rounded_corner_radius_top, fillValue); mTestableContext.getOrCreateTestableResources().addOverride( R.array.config_roundedCornerBottomRadiusArray, mMockRoundedCornersRadiusArray); mTestableContext.getOrCreateTestableResources().addOverride( R.dimen.rounded_corner_radius_bottom, fillValue); } private DesktopModeWindowDecoration createWindowDecoration( ActivityManager.RunningTaskInfo taskInfo) { return new DesktopModeWindowDecoration(mContext, mMockDisplayController, Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java +37 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,26 @@ public class DesktopModeStatus { private static final boolean IS_STASHING_ENABLED = SystemProperties.getBoolean( "persist.wm.debug.desktop_stashing", false); /** * Flag to indicate whether to apply shadows to windows in desktop mode. */ private static final boolean USE_WINDOW_SHADOWS = SystemProperties.getBoolean( "persist.wm.debug.desktop_use_window_shadows", true); /** * Flag to indicate whether to apply shadows to the focused window in desktop mode. * * Note: this flag is only relevant if USE_WINDOW_SHADOWS is false. */ private static final boolean USE_WINDOW_SHADOWS_FOCUSED_WINDOW = SystemProperties.getBoolean( "persist.wm.debug.desktop_use_window_shadows_focused_window", false); /** * Flag to indicate whether to apply shadows to windows in desktop mode. */ private static final boolean USE_ROUNDED_CORNERS = SystemProperties.getBoolean( "persist.wm.debug.desktop_use_rounded_corners", true); /** * Return {@code true} is desktop windowing proto 2 is enabled */ Loading Loading @@ -81,4 +101,21 @@ public class DesktopModeStatus { public static boolean isStashingEnabled() { return IS_STASHING_ENABLED; } /** * Return whether to use window shadows. * * @param isFocusedWindow whether the window to apply shadows to is focused */ public static boolean useWindowShadow(boolean isFocusedWindow) { return USE_WINDOW_SHADOWS || (USE_WINDOW_SHADOWS_FOCUSED_WINDOW && isFocusedWindow); } /** * Return whether to use rounded corners for windows. */ public static boolean useRoundedCorners() { return USE_ROUNDED_CORNERS; } }
libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +3 −0 Original line number Diff line number Diff line Loading @@ -721,6 +721,9 @@ class DesktopTasksController( finishTransaction: SurfaceControl.Transaction ) { // Add rounded corners to freeform windows if (!DesktopModeStatus.useRoundedCorners()) { return } val cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context) info.changes .filter { it.taskInfo?.windowingMode == WINDOWING_MODE_FREEFORM } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +50 −33 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ import android.view.ViewConfiguration; import android.widget.ImageButton; import android.window.WindowContainerTransaction; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.policy.ScreenDecorationsUtils; import com.android.launcher3.icons.BaseIconFactory; import com.android.launcher3.icons.IconProvider; Loading Loading @@ -195,46 +196,16 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin void relayout(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT, boolean applyStartTransactionOnDraw) { final int shadowRadiusID = taskInfo.isFocused ? R.dimen.freeform_decor_shadow_focused_thickness : R.dimen.freeform_decor_shadow_unfocused_thickness; final boolean isFreeform = taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM; final boolean isDragResizeable = isFreeform && taskInfo.isResizeable; if (isHandleMenuActive()) { mHandleMenu.relayout(startT); } updateRelayoutParams(mRelayoutParams, mContext, taskInfo, applyStartTransactionOnDraw); final WindowDecorLinearLayout oldRootView = mResult.mRootView; final SurfaceControl oldDecorationSurface = mDecorationContainerSurface; final WindowContainerTransaction wct = new WindowContainerTransaction(); final int windowDecorLayoutId = getDesktopModeWindowDecorLayoutId( taskInfo.getWindowingMode()); mRelayoutParams.reset(); mRelayoutParams.mRunningTaskInfo = taskInfo; mRelayoutParams.mLayoutResId = windowDecorLayoutId; mRelayoutParams.mCaptionHeightId = getCaptionHeightId(taskInfo.getWindowingMode()); mRelayoutParams.mShadowRadiusId = shadowRadiusID; mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw; // The configuration used to lay out the window decoration. The system context's config is // used when the task density has been overridden to a custom density so that the resources // and views of the decoration aren't affected and match the rest of the System UI, if not // then just use the task's configuration. A copy is made instead of using the original // reference so that the configuration isn't mutated on config changes and diff checks can // be made in WindowDecoration#relayout using the pre/post-relayout configuration. // See b/301119301. // TODO(b/301119301): consider moving the config data needed for diffs to relayout params // instead of using a whole Configuration as a parameter. final Configuration windowDecorConfig = new Configuration(); windowDecorConfig.setTo(DesktopTasksController.isDesktopDensityOverrideSet() ? mContext.getResources().getConfiguration() // Use system context. : mTaskInfo.configuration); // Use task configuration. mRelayoutParams.mWindowDecorConfig = windowDecorConfig; mRelayoutParams.mCornerRadius = (int) ScreenDecorationsUtils.getWindowCornerRadius(mContext); relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult); // After this line, mTaskInfo is up-to-date and should be used instead of taskInfo Loading Loading @@ -273,6 +244,9 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin closeMaximizeMenu(); } final boolean isFreeform = taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM; final boolean isDragResizeable = isFreeform && taskInfo.isResizeable; if (!isDragResizeable) { if (!mTaskInfo.positionInParent.equals(mPositionInParent)) { // We still want to track caption bar's exclusion region on a non-resizeable task. Loading Loading @@ -323,6 +297,45 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin } } @VisibleForTesting static void updateRelayoutParams( RelayoutParams relayoutParams, Context context, ActivityManager.RunningTaskInfo taskInfo, boolean applyStartTransactionOnDraw) { relayoutParams.reset(); relayoutParams.mRunningTaskInfo = taskInfo; relayoutParams.mLayoutResId = getDesktopModeWindowDecorLayoutId(taskInfo.getWindowingMode()); relayoutParams.mCaptionHeightId = getCaptionHeightIdStatic(taskInfo.getWindowingMode()); if (DesktopModeStatus.useWindowShadow(/* isFocusedWindow= */ taskInfo.isFocused)) { relayoutParams.mShadowRadiusId = taskInfo.isFocused ? R.dimen.freeform_decor_shadow_focused_thickness : R.dimen.freeform_decor_shadow_unfocused_thickness; } relayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw; // The configuration used to lay out the window decoration. The system context's config is // used when the task density has been overridden to a custom density so that the resources // and views of the decoration aren't affected and match the rest of the System UI, if not // then just use the task's configuration. A copy is made instead of using the original // reference so that the configuration isn't mutated on config changes and diff checks can // be made in WindowDecoration#relayout using the pre/post-relayout configuration. // See b/301119301. // TODO(b/301119301): consider moving the config data needed for diffs to relayout params // instead of using a whole Configuration as a parameter. final Configuration windowDecorConfig = new Configuration(); windowDecorConfig.setTo(DesktopTasksController.isDesktopDensityOverrideSet() ? context.getResources().getConfiguration() // Use system context. : taskInfo.configuration); // Use task configuration. relayoutParams.mWindowDecorConfig = windowDecorConfig; if (DesktopModeStatus.useRoundedCorners()) { relayoutParams.mCornerRadius = (int) ScreenDecorationsUtils.getWindowCornerRadius(context); } } private PointF calculateMaximizeMenuPosition() { final PointF position = new PointF(); final Resources resources = mContext.getResources(); Loading Loading @@ -684,7 +697,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin super.close(); } private int getDesktopModeWindowDecorLayoutId(@WindowingMode int windowingMode) { private static int getDesktopModeWindowDecorLayoutId(@WindowingMode int windowingMode) { return windowingMode == WINDOWING_MODE_FREEFORM ? R.layout.desktop_mode_app_controls_window_decor : R.layout.desktop_mode_focused_window_decor; Loading Loading @@ -730,6 +743,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin @Override int getCaptionHeightId(@WindowingMode int windowingMode) { return getCaptionHeightIdStatic(windowingMode); } private static int getCaptionHeightIdStatic(@WindowingMode int windowingMode) { return windowingMode == WINDOWING_MODE_FULLSCREEN ? R.dimen.desktop_mode_fullscreen_decor_caption_height : R.dimen.desktop_mode_freeform_decor_caption_height; Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java +77 −0 Original line number Diff line number Diff line Loading @@ -16,16 +16,24 @@ package com.android.wm.shell.windowdecor; import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.any; import static org.mockito.Mockito.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.ActivityManager; import android.content.ComponentName; import android.content.res.Configuration; import android.content.res.Resources; import android.content.res.TypedArray; import android.os.Handler; import android.os.SystemProperties; import android.testing.AndroidTestingRunner; import android.testing.TestableContext; import android.view.Choreographer; import android.view.Display; import android.view.SurfaceControl; Loading @@ -34,14 +42,17 @@ import android.window.WindowContainerTransaction; import androidx.test.filters.SmallTest; import com.android.internal.R; import com.android.wm.shell.RootTaskDisplayAreaOrganizer; import com.android.wm.shell.ShellTaskOrganizer; import com.android.wm.shell.ShellTestCase; import com.android.wm.shell.TestRunningTaskInfoBuilder; import com.android.wm.shell.common.DisplayController; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.windowdecor.WindowDecoration.RelayoutParams; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; Loading @@ -57,6 +68,13 @@ import java.util.function.Supplier; @SmallTest @RunWith(AndroidTestingRunner.class) public class DesktopModeWindowDecorationTests extends ShellTestCase { private static final String USE_WINDOW_SHADOWS_SYSPROP_KEY = "persist.wm.debug.desktop_use_window_shadows"; private static final String FOCUSED_USE_WINDOW_SHADOWS_SYSPROP_KEY = "persist.wm.debug.desktop_use_window_shadows_focused_window"; private static final String USE_ROUNDED_CORNERS_SYSPROP_KEY = "persist.wm.debug.desktop_use_rounded_corners"; @Mock private DisplayController mMockDisplayController; @Mock Loading @@ -79,14 +97,29 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { private SurfaceControlViewHost mMockSurfaceControlViewHost; @Mock private WindowDecoration.SurfaceControlViewHostFactory mMockSurfaceControlViewHostFactory; @Mock private TypedArray mMockRoundedCornersRadiusArray; private final Configuration mConfiguration = new Configuration(); private TestableContext mTestableContext; /** Set up run before test class. */ @BeforeClass public static void setUpClass() { // Reset the sysprop settings before running the test. SystemProperties.set(USE_WINDOW_SHADOWS_SYSPROP_KEY, ""); SystemProperties.set(FOCUSED_USE_WINDOW_SHADOWS_SYSPROP_KEY, ""); SystemProperties.set(USE_ROUNDED_CORNERS_SYSPROP_KEY, ""); } @Before public void setUp() { doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory).create( any(), any(), any()); doReturn(mMockTransaction).when(mMockTransactionSupplier).get(); mTestableContext = new TestableContext(mContext); mTestableContext.ensureTestableResources(); } @Test Loading @@ -105,6 +138,50 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { } @Test public void updateRelayoutParams_noSysPropFlagsSet_windowShadowsAreEnabled() { final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); RelayoutParams relayoutParams = new RelayoutParams(); DesktopModeWindowDecoration.updateRelayoutParams( relayoutParams, mContext, taskInfo, /* applyStartTransactionOnDraw= */ true); assertThat(relayoutParams.mShadowRadiusId).isNotEqualTo(Resources.ID_NULL); } @Test public void updateRelayoutParams_noSysPropFlagsSet_roundedCornersAreEnabled() { final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); fillRoundedCornersResources(/* fillValue= */ 30); RelayoutParams relayoutParams = new RelayoutParams(); DesktopModeWindowDecoration.updateRelayoutParams( relayoutParams, mTestableContext, taskInfo, /* applyStartTransactionOnDraw= */ true); assertThat(relayoutParams.mCornerRadius).isGreaterThan(0); } private void fillRoundedCornersResources(int fillValue) { when(mMockRoundedCornersRadiusArray.getDimensionPixelSize(anyInt(), anyInt())) .thenReturn(fillValue); mTestableContext.getOrCreateTestableResources().addOverride( R.array.config_roundedCornerRadiusArray, mMockRoundedCornersRadiusArray); mTestableContext.getOrCreateTestableResources().addOverride( R.dimen.rounded_corner_radius, fillValue); mTestableContext.getOrCreateTestableResources().addOverride( R.array.config_roundedCornerTopRadiusArray, mMockRoundedCornersRadiusArray); mTestableContext.getOrCreateTestableResources().addOverride( R.dimen.rounded_corner_radius_top, fillValue); mTestableContext.getOrCreateTestableResources().addOverride( R.array.config_roundedCornerBottomRadiusArray, mMockRoundedCornersRadiusArray); mTestableContext.getOrCreateTestableResources().addOverride( R.dimen.rounded_corner_radius_bottom, fillValue); } private DesktopModeWindowDecoration createWindowDecoration( ActivityManager.RunningTaskInfo taskInfo) { return new DesktopModeWindowDecoration(mContext, mMockDisplayController, Loading