diff options
4 files changed, 48 insertions, 37 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java index 3946b6173b0b..c9546731a193 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecoration.java @@ -180,12 +180,13 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL // all other cases, it is expected that the transition handler positions and crops the task // in order to allow the handler time to animate before the task before the final // position and crop are set. - final boolean shouldSetTaskPositionAndCrop = mTaskDragResizer.isResizingOrAnimating(); + final boolean shouldSetTaskVisibilityPositionAndCrop = + mTaskDragResizer.isResizingOrAnimating(); // Use |applyStartTransactionOnDraw| so that the transaction (that applies task crop) is // synced with the buffer transaction (that draws the View). Both will be shown on screen // at the same, whereas applying them independently causes flickering. See b/270202228. relayout(taskInfo, t, t, true /* applyStartTransactionOnDraw */, - shouldSetTaskPositionAndCrop, hasGlobalFocus); + shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus); } @VisibleForTesting @@ -193,7 +194,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL RelayoutParams relayoutParams, ActivityManager.RunningTaskInfo taskInfo, boolean applyStartTransactionOnDraw, - boolean setTaskCropAndPosition, + boolean shouldSetTaskVisibilityPositionAndCrop, boolean isStatusBarVisible, boolean isKeyguardVisibleAndOccluded, InsetsState displayInsetsState, @@ -206,7 +207,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL ? R.dimen.freeform_decor_shadow_focused_thickness : R.dimen.freeform_decor_shadow_unfocused_thickness; relayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw; - relayoutParams.mSetTaskPositionAndCrop = setTaskCropAndPosition; + relayoutParams.mSetTaskVisibilityPositionAndCrop = shouldSetTaskVisibilityPositionAndCrop; relayoutParams.mIsCaptionVisible = taskInfo.isFreeform() || (isStatusBarVisible && !isKeyguardVisibleAndOccluded); @@ -234,7 +235,7 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL @SuppressLint("MissingPermission") void relayout(RunningTaskInfo taskInfo, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT, - boolean applyStartTransactionOnDraw, boolean setTaskCropAndPosition, + boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop, boolean hasGlobalFocus) { final boolean isFreeform = taskInfo.getWindowingMode() == WindowConfiguration.WINDOWING_MODE_FREEFORM; @@ -246,7 +247,8 @@ public class CaptionWindowDecoration extends WindowDecoration<WindowDecorLinearL final WindowContainerTransaction wct = new WindowContainerTransaction(); updateRelayoutParams(mRelayoutParams, taskInfo, applyStartTransactionOnDraw, - setTaskCropAndPosition, mIsStatusBarVisible, mIsKeyguardVisibleAndOccluded, + shouldSetTaskVisibilityPositionAndCrop, mIsStatusBarVisible, + mIsKeyguardVisibleAndOccluded, mDisplayController.getInsetsState(taskInfo.displayId), hasGlobalFocus); relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java index 9f37358b6044..62c2e191a6a2 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java @@ -392,18 +392,25 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin @Override void relayout(ActivityManager.RunningTaskInfo taskInfo, boolean hasGlobalFocus) { final SurfaceControl.Transaction t = mSurfaceControlTransactionSupplier.get(); - // The crop and position of the task should only be set when a task is fluid resizing. In - // all other cases, it is expected that the transition handler positions and crops the task - // in order to allow the handler time to animate before the task before the final - // position and crop are set. - final boolean shouldSetTaskPositionAndCrop = !DesktopModeStatus.isVeiledResizeEnabled() - && mTaskDragResizer.isResizingOrAnimating(); + // The visibility, crop and position of the task should only be set when a task is + // fluid resizing. In all other cases, it is expected that the transition handler sets + // those task properties to allow the handler time to animate with full control of the task + // leash. In general, allowing the window decoration to set any of these is likely to cause + // incorrect frames and flickering because relayouts from TaskListener#onTaskInfoChanged + // aren't synchronized with shell transition callbacks, so if they come too early it + // might show/hide or crop the task at a bad time. + // Fluid resizing is exempt from this because it intentionally doesn't use shell + // transitions to resize the task, so onTaskInfoChanged relayouts is the only way to make + // sure the crop is set correctly. + final boolean shouldSetTaskVisibilityPositionAndCrop = + !DesktopModeStatus.isVeiledResizeEnabled() + && mTaskDragResizer.isResizingOrAnimating(); // For headers only (i.e. in freeform): use |applyStartTransactionOnDraw| so that the // transaction (that applies task crop) is synced with the buffer transaction (that draws // the View). Both will be shown on screen at the same, whereas applying them independently // causes flickering. See b/270202228. final boolean applyTransactionOnDraw = taskInfo.isFreeform(); - relayout(taskInfo, t, t, applyTransactionOnDraw, shouldSetTaskPositionAndCrop, + relayout(taskInfo, t, t, applyTransactionOnDraw, shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus); if (!applyTransactionOnDraw) { t.apply(); @@ -430,19 +437,19 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin void relayout(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT, - boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop, + boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop, boolean hasGlobalFocus) { Trace.beginSection("DesktopModeWindowDecoration#relayout"); if (taskInfo.isFreeform()) { // The Task is in Freeform mode -> show its header in sync since it's an integral part // of the window itself - a delayed header might cause bad UX. relayoutInSync(taskInfo, startT, finishT, applyStartTransactionOnDraw, - shouldSetTaskPositionAndCrop, hasGlobalFocus); + shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus); } else { // The Task is outside Freeform mode -> allow the handle view to be delayed since the // handle is just a small addition to the window. relayoutWithDelayedViewHost(taskInfo, startT, finishT, applyStartTransactionOnDraw, - shouldSetTaskPositionAndCrop, hasGlobalFocus); + shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus); } Trace.endSection(); } @@ -450,12 +457,12 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin /** Run the whole relayout phase immediately without delay. */ private void relayoutInSync(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT, - boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop, + boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop, boolean hasGlobalFocus) { // Clear the current ViewHost runnable as we will update the ViewHost here clearCurrentViewHostRunnable(); updateRelayoutParamsAndSurfaces(taskInfo, startT, finishT, applyStartTransactionOnDraw, - shouldSetTaskPositionAndCrop, hasGlobalFocus); + shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus); if (mResult.mRootView != null) { updateViewHost(mRelayoutParams, startT, mResult); } @@ -477,7 +484,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin */ private void relayoutWithDelayedViewHost(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT, - boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop, + boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop, boolean hasGlobalFocus) { if (applyStartTransactionOnDraw) { throw new IllegalArgumentException( @@ -486,7 +493,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin // Clear the current ViewHost runnable as we will update the ViewHost here clearCurrentViewHostRunnable(); updateRelayoutParamsAndSurfaces(taskInfo, startT, finishT, - false /* applyStartTransactionOnDraw */, shouldSetTaskPositionAndCrop, + false /* applyStartTransactionOnDraw */, shouldSetTaskVisibilityPositionAndCrop, hasGlobalFocus); if (mResult.mRootView == null) { // This means something blocks the window decor from showing, e.g. the task is hidden. @@ -501,7 +508,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin @SuppressLint("MissingPermission") private void updateRelayoutParamsAndSurfaces(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT, - boolean applyStartTransactionOnDraw, boolean shouldSetTaskPositionAndCrop, + boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop, boolean hasGlobalFocus) { Trace.beginSection("DesktopModeWindowDecoration#updateRelayoutParamsAndSurfaces"); @@ -526,9 +533,9 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin final boolean inFullImmersive = mDesktopRepository .isTaskInFullImmersiveState(taskInfo.taskId); updateRelayoutParams(mRelayoutParams, mContext, taskInfo, applyStartTransactionOnDraw, - shouldSetTaskPositionAndCrop, mIsStatusBarVisible, mIsKeyguardVisibleAndOccluded, - inFullImmersive, mDisplayController.getInsetsState(taskInfo.displayId), - hasGlobalFocus); + shouldSetTaskVisibilityPositionAndCrop, mIsStatusBarVisible, + mIsKeyguardVisibleAndOccluded, inFullImmersive, + mDisplayController.getInsetsState(taskInfo.displayId), hasGlobalFocus); final WindowDecorLinearLayout oldRootView = mResult.mRootView; final SurfaceControl oldDecorationSurface = mDecorationContainerSurface; @@ -857,7 +864,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin Context context, ActivityManager.RunningTaskInfo taskInfo, boolean applyStartTransactionOnDraw, - boolean shouldSetTaskPositionAndCrop, + boolean shouldSetTaskVisibilityPositionAndCrop, boolean isStatusBarVisible, boolean isKeyguardVisibleAndOccluded, boolean inFullImmersiveMode, @@ -953,7 +960,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin : R.dimen.freeform_decor_shadow_unfocused_thickness; } relayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw; - relayoutParams.mSetTaskPositionAndCrop = shouldSetTaskPositionAndCrop; + relayoutParams.mSetTaskVisibilityPositionAndCrop = shouldSetTaskVisibilityPositionAndCrop; // The configuration used to layout the window decoration. A copy is made instead of using // the original reference so that the configuration isn't mutated on config changes and diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java index f97dfb89bc0d..b016c755e323 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java @@ -249,7 +249,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> if (!mTaskInfo.isVisible) { releaseViews(wct); - finishT.hide(mTaskSurface); + if (params.mSetTaskVisibilityPositionAndCrop) { + finishT.hide(mTaskSurface); + } return; } @@ -422,7 +424,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> private void updateTaskSurface(RelayoutParams params, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT, RelayoutResult<T> outResult) { - if (params.mSetTaskPositionAndCrop) { + if (params.mSetTaskVisibilityPositionAndCrop) { final Point taskPosition = mTaskInfo.positionInParent; startT.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight); finishT.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight) @@ -437,9 +439,13 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> shadowRadius = loadDimension(mDecorWindowContext.getResources(), params.mShadowRadiusId); } - startT.setShadowRadius(mTaskSurface, shadowRadius).show(mTaskSurface); + startT.setShadowRadius(mTaskSurface, shadowRadius); finishT.setShadowRadius(mTaskSurface, shadowRadius); + if (params.mSetTaskVisibilityPositionAndCrop) { + startT.show(mTaskSurface); + } + if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) { if (!DesktopModeStatus.isVeiledResizeEnabled()) { // When fluid resize is enabled, add a background to freeform tasks @@ -758,7 +764,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> Configuration mWindowDecorConfig; boolean mApplyStartTransactionOnDraw; - boolean mSetTaskPositionAndCrop; + boolean mSetTaskVisibilityPositionAndCrop; boolean mHasGlobalFocus; void reset() { @@ -777,7 +783,7 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> mIsCaptionVisible = false; mApplyStartTransactionOnDraw = false; - mSetTaskPositionAndCrop = false; + mSetTaskVisibilityPositionAndCrop = false; mWindowDecorConfig = null; mHasGlobalFocus = false; } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java index cb7fadee9822..8e0434cb28f7 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java @@ -218,8 +218,6 @@ public class WindowDecorationTests extends ShellTestCase { verify(captionContainerSurfaceBuilder, never()).build(); verify(mMockSurfaceControlViewHostFactory, never()).create(any(), any(), any()); - verify(mMockSurfaceControlFinishT).hide(mMockTaskSurface); - assertNull(mRelayoutResult.mRootView); } @@ -281,8 +279,6 @@ public class WindowDecorationTests extends ShellTestCase { verify(mMockSurfaceControlStartT).setCornerRadius(mMockTaskSurface, CORNER_RADIUS); verify(mMockSurfaceControlFinishT).setCornerRadius(mMockTaskSurface, CORNER_RADIUS); - verify(mMockSurfaceControlStartT) - .show(mMockTaskSurface); verify(mMockSurfaceControlStartT).setShadowRadius(mMockTaskSurface, 10); assertEquals(300, mRelayoutResult.mWidth); @@ -863,7 +859,7 @@ public class WindowDecorationTests extends ShellTestCase { final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo); - mRelayoutParams.mSetTaskPositionAndCrop = false; + mRelayoutParams.mSetTaskVisibilityPositionAndCrop = false; windowDecor.relayout(taskInfo, true /* hasGlobalFocus */); verify(mMockSurfaceControlStartT, never()).setWindowCrop( @@ -891,7 +887,7 @@ public class WindowDecorationTests extends ShellTestCase { taskInfo.configuration.densityDpi = DisplayMetrics.DENSITY_DEFAULT * 2; final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo); - mRelayoutParams.mSetTaskPositionAndCrop = true; + mRelayoutParams.mSetTaskVisibilityPositionAndCrop = true; windowDecor.relayout(taskInfo, true /* hasGlobalFocus */); verify(mMockSurfaceControlStartT).setWindowCrop( |