diff options
| author | 2025-01-13 08:27:12 -0800 | |
|---|---|---|
| committer | 2025-01-15 04:35:07 -0800 | |
| commit | 7df1f96d0fac39d51f615765acd403257ac6a5ee (patch) | |
| tree | 57a1d869aa0b8f5f68b84ed6386ce44a787a025c | |
| parent | 4f783b4ec82364d856394c5817bc52949130a69a (diff) | |
Reland "Swipe-up Recents transition: override desktop tasks corner..."
Fix an issue where the corner radius and shadow of Desktop tasks are
incorrectly applied during the Recents swipe-up transition:
Shell and Launcher uses different leashes to control Desktop tasks
during transitions, and there is a bug (b/200300845 ) where applying
different corner radii to several ancestors (with different bounds) of
a single task causes bad results (it's unclear clear what corner radii
is applied, and the task shadow might leak outside an ancestor as well).
With this CL we
1. tell WindowDecoration to avoid updating the corner radius of Desktop
tasks during Recents transitions, and
2. pass a TransitionInfo object to Launcher during Recents transitions
to allow Launcher to access the task leashes used by Shell, and
override the corner radius of the relevant tasks.
Bug: 378657004
Test: manual
Flag: com.android.window.flags.enable_desktop_recents_transitions_corners_bugfix
Change-Id: Ie714406143c0590e0f2f1374d2b64f48a6b9c632
11 files changed, 198 insertions, 34 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java index ac510f89b905..e8add56619c4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellModule.java @@ -946,7 +946,8 @@ public abstract class WMShellModule { FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, DesktopModeUiEventLogger desktopModeUiEventLogger, - WindowDecorTaskResourceLoader taskResourceLoader + WindowDecorTaskResourceLoader taskResourceLoader, + RecentsTransitionHandler recentsTransitionHandler ) { if (!DesktopModeStatus.canEnterDesktopModeOrShowAppHandle(context)) { return Optional.empty(); @@ -962,7 +963,7 @@ public abstract class WMShellModule { desktopTasksLimiter, appHandleEducationController, appToWebEducationController, windowDecorCaptionHandleRepository, activityOrientationChangeHandler, focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger, - taskResourceLoader)); + taskResourceLoader, recentsTransitionHandler)); } @WMSingleton diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationRunner.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationRunner.aidl index 32c79a2d02de..8cdb8c4512a9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationRunner.aidl +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/IRecentsAnimationRunner.aidl @@ -17,9 +17,10 @@ package com.android.wm.shell.recents; import android.graphics.Rect; +import android.os.Bundle; import android.view.RemoteAnimationTarget; import android.window.TaskSnapshot; -import android.os.Bundle; +import android.window.TransitionInfo; import com.android.wm.shell.recents.IRecentsAnimationController; @@ -57,7 +58,8 @@ oneway interface IRecentsAnimationRunner { */ void onAnimationStart(in IRecentsAnimationController controller, in RemoteAnimationTarget[] apps, in RemoteAnimationTarget[] wallpapers, - in Rect homeContentInsets, in Rect minimizedHomeBounds, in Bundle extras) = 2; + in Rect homeContentInsets, in Rect minimizedHomeBounds, in Bundle extras, + in TransitionInfo info) = 2; /** * Called when the task of an activity that has been started while the recents animation diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java index db582aa30f6a..aeccd86e122c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/recents/RecentsTransitionHandler.java @@ -587,7 +587,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler, mListener.onAnimationStart(this, apps.toArray(new RemoteAnimationTarget[apps.size()]), new RemoteAnimationTarget[0], - new Rect(0, 0, 0, 0), new Rect(), new Bundle()); + new Rect(0, 0, 0, 0), new Rect(), new Bundle(), + null); for (int i = 0; i < mStateListeners.size(); i++) { mStateListeners.get(i).onTransitionStateChanged(TRANSITION_STATE_ANIMATING); } @@ -818,7 +819,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler, mListener.onAnimationStart(this, apps.toArray(new RemoteAnimationTarget[apps.size()]), wallpapers.toArray(new RemoteAnimationTarget[wallpapers.size()]), - new Rect(0, 0, 0, 0), new Rect(), b); + new Rect(0, 0, 0, 0), new Rect(), b, info); for (int i = 0; i < mStateListeners.size(); i++) { mStateListeners.get(i).onTransitionStateChanged(TRANSITION_STATE_ANIMATING); } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java index 67dae283345a..055bc8f5f092 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModel.java @@ -126,6 +126,8 @@ import com.android.wm.shell.desktopmode.common.ToggleTaskSizeUtilsKt; import com.android.wm.shell.desktopmode.education.AppHandleEducationController; import com.android.wm.shell.desktopmode.education.AppToWebEducationController; import com.android.wm.shell.freeform.FreeformTaskTransitionStarter; +import com.android.wm.shell.recents.RecentsTransitionHandler; +import com.android.wm.shell.recents.RecentsTransitionStateListener; import com.android.wm.shell.shared.FocusTransitionListener; import com.android.wm.shell.shared.annotations.ShellBackgroundThread; import com.android.wm.shell.shared.annotations.ShellMainThread; @@ -157,8 +159,10 @@ import kotlinx.coroutines.MainCoroutineDispatcher; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.function.Supplier; /** @@ -247,6 +251,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, private final DesktopModeEventLogger mDesktopModeEventLogger; private final DesktopModeUiEventLogger mDesktopModeUiEventLogger; private final WindowDecorTaskResourceLoader mTaskResourceLoader; + private final RecentsTransitionHandler mRecentsTransitionHandler; public DesktopModeWindowDecorViewModel( Context context, @@ -282,7 +287,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, DesktopModeUiEventLogger desktopModeUiEventLogger, - WindowDecorTaskResourceLoader taskResourceLoader) { + WindowDecorTaskResourceLoader taskResourceLoader, + RecentsTransitionHandler recentsTransitionHandler) { this( context, shellExecutor, @@ -323,7 +329,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, focusTransitionObserver, desktopModeEventLogger, desktopModeUiEventLogger, - taskResourceLoader); + taskResourceLoader, + recentsTransitionHandler); } @VisibleForTesting @@ -367,7 +374,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, FocusTransitionObserver focusTransitionObserver, DesktopModeEventLogger desktopModeEventLogger, DesktopModeUiEventLogger desktopModeUiEventLogger, - WindowDecorTaskResourceLoader taskResourceLoader) { + WindowDecorTaskResourceLoader taskResourceLoader, + RecentsTransitionHandler recentsTransitionHandler) { mContext = context; mMainExecutor = shellExecutor; mMainHandler = mainHandler; @@ -436,6 +444,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, mDesktopModeEventLogger = desktopModeEventLogger; mDesktopModeUiEventLogger = desktopModeUiEventLogger; mTaskResourceLoader = taskResourceLoader; + mRecentsTransitionHandler = recentsTransitionHandler; shellInit.addInitCallback(this::onInit, this); } @@ -450,6 +459,10 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, new DesktopModeOnTaskResizeAnimationListener()); mDesktopTasksController.setOnTaskRepositionAnimationListener( new DesktopModeOnTaskRepositionAnimationListener()); + if (Flags.enableDesktopRecentsTransitionsCornersBugfix()) { + mRecentsTransitionHandler.addTransitionStateListener( + new DesktopModeRecentsTransitionStateListener()); + } mDisplayController.addDisplayChangingController(mOnDisplayChangingListener); try { mWindowManager.registerSystemGestureExclusionListener(mGestureExclusionListener, @@ -1859,6 +1872,38 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, } } + private class DesktopModeRecentsTransitionStateListener + implements RecentsTransitionStateListener { + final Set<Integer> mAnimatingTaskIds = new HashSet<>(); + + @Override + public void onTransitionStateChanged(int state) { + switch (state) { + case RecentsTransitionStateListener.TRANSITION_STATE_REQUESTED: + for (int n = 0; n < mWindowDecorByTaskId.size(); n++) { + int taskId = mWindowDecorByTaskId.keyAt(n); + mAnimatingTaskIds.add(taskId); + setIsRecentsTransitionRunningForTask(taskId, true); + } + return; + case RecentsTransitionStateListener.TRANSITION_STATE_NOT_RUNNING: + // No Recents transition running - clean up window decorations + for (int taskId : mAnimatingTaskIds) { + setIsRecentsTransitionRunningForTask(taskId, false); + } + mAnimatingTaskIds.clear(); + return; + default: + } + } + + private void setIsRecentsTransitionRunningForTask(int taskId, boolean isRecentsRunning) { + final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskId); + if (decoration == null) return; + decoration.setIsRecentsTransitionRunning(isRecentsRunning); + } + } + private class DragEventListenerImpl implements DragPositioningCallbackUtility.DragEventListener { @Override 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 4ac89546c9c7..39a989ce7c7f 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 @@ -204,6 +204,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin private final MultiInstanceHelper mMultiInstanceHelper; private final WindowDecorCaptionHandleRepository mWindowDecorCaptionHandleRepository; private final DesktopUserRepositories mDesktopUserRepositories; + private boolean mIsRecentsTransitionRunning = false; private Runnable mLoadAppInfoRunnable; private Runnable mSetAppInfoRunnable; @@ -498,7 +499,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin applyStartTransactionOnDraw, shouldSetTaskVisibilityPositionAndCrop, mIsStatusBarVisible, mIsKeyguardVisibleAndOccluded, inFullImmersive, mDisplayController.getInsetsState(taskInfo.displayId), hasGlobalFocus, - displayExclusionRegion); + displayExclusionRegion, mIsRecentsTransitionRunning); final WindowDecorLinearLayout oldRootView = mResult.mRootView; final SurfaceControl oldDecorationSurface = mDecorationContainerSurface; @@ -869,7 +870,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin boolean inFullImmersiveMode, @NonNull InsetsState displayInsetsState, boolean hasGlobalFocus, - @NonNull Region displayExclusionRegion) { + @NonNull Region displayExclusionRegion, + boolean shouldIgnoreCornerRadius) { final int captionLayoutId = getDesktopModeWindowDecorLayoutId(taskInfo.getWindowingMode()); final boolean isAppHeader = captionLayoutId == R.layout.desktop_mode_app_header; @@ -1006,13 +1008,19 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin relayoutParams.mWindowDecorConfig = windowDecorConfig; if (DesktopModeStatus.useRoundedCorners()) { - relayoutParams.mCornerRadius = taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM - ? loadDimensionPixelSize(context.getResources(), - R.dimen.desktop_windowing_freeform_rounded_corner_radius) - : INVALID_CORNER_RADIUS; + relayoutParams.mCornerRadius = shouldIgnoreCornerRadius ? INVALID_CORNER_RADIUS : + getCornerRadius(context, relayoutParams.mLayoutResId); } } + private static int getCornerRadius(@NonNull Context context, int layoutResId) { + if (layoutResId == R.layout.desktop_mode_app_header) { + return loadDimensionPixelSize(context.getResources(), + R.dimen.desktop_windowing_freeform_rounded_corner_radius); + } + return INVALID_CORNER_RADIUS; + } + /** * If task has focused window decor, return the caption id of the fullscreen caption size * resource. Otherwise, return ID_NULL and caption width be set to task width. @@ -1740,6 +1748,17 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin } /** + * Declares whether a Recents transition is currently active. + * + * <p> When a Recents transition is active we allow that transition to take ownership of the + * corner radius of its task surfaces, so each window decoration should stop updating the corner + * radius of its task surface during that time. + */ + void setIsRecentsTransitionRunning(boolean isRecentsTransitionRunning) { + mIsRecentsTransitionRunning = isRecentsTransitionRunning; + } + + /** * Called when there is a {@link MotionEvent#ACTION_HOVER_EXIT} on the maximize window button. */ void onMaximizeButtonHoverExit() { 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 5d1bedb85b5e..fa7183ad0fd8 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 @@ -967,4 +967,4 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer> return Objects.hash(mToken, mOwner, mFrame, Arrays.hashCode(mBoundingRects), mFlags); } } -}
\ No newline at end of file +} diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java index 894d238b7e15..ab43119b14c0 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/recents/RecentsTransitionHandlerTest.java @@ -169,7 +169,7 @@ public class RecentsTransitionHandlerTest extends ShellTestCase { final IResultReceiver finishCallback = mock(IResultReceiver.class); final IBinder transition = startRecentsTransition(/* synthetic= */ true, runner); - verify(runner).onAnimationStart(any(), any(), any(), any(), any(), any()); + verify(runner).onAnimationStart(any(), any(), any(), any(), any(), any(), any()); // Finish and verify no transition remains and that the provided finish callback is called mRecentsTransitionHandler.findController(transition).finish(true /* toHome */, @@ -184,7 +184,7 @@ public class RecentsTransitionHandlerTest extends ShellTestCase { final IRecentsAnimationRunner runner = mock(IRecentsAnimationRunner.class); final IBinder transition = startRecentsTransition(/* synthetic= */ true, runner); - verify(runner).onAnimationStart(any(), any(), any(), any(), any(), any()); + verify(runner).onAnimationStart(any(), any(), any(), any(), any(), any(), any()); mRecentsTransitionHandler.findController(transition).cancel("test"); mMainExecutor.flushAll(); diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt index ffe8e7135513..79e9b9c8cd77 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTests.kt @@ -59,11 +59,12 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn import com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession import com.android.window.flags.Flags import com.android.wm.shell.R -import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction import com.android.wm.shell.desktopmode.DesktopImmersiveController import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.InputMethod import com.android.wm.shell.desktopmode.DesktopModeEventLogger.Companion.ResizeTrigger import com.android.wm.shell.desktopmode.DesktopTasksController.SnapPosition +import com.android.wm.shell.desktopmode.common.ToggleTaskSizeInteraction +import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.shared.desktopmode.DesktopModeStatus import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.splitscreen.SplitScreenController @@ -539,7 +540,8 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest onLeftSnapClickListenerCaptor.value.invoke() verify(mockDesktopTasksController, never()) - .snapToHalfScreen(eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.LEFT), + .snapToHalfScreen( + eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.LEFT), eq(ResizeTrigger.MAXIMIZE_BUTTON), eq(InputMethod.UNKNOWN_INPUT_METHOD), eq(decor), @@ -616,11 +618,12 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest onRightSnapClickListenerCaptor.value.invoke() verify(mockDesktopTasksController, never()) - .snapToHalfScreen(eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.RIGHT), + .snapToHalfScreen( + eq(decor.mTaskInfo), any(), eq(currentBounds), eq(SnapPosition.RIGHT), eq(ResizeTrigger.MAXIMIZE_BUTTON), eq(InputMethod.UNKNOWN_INPUT_METHOD), eq(decor), - ) + ) } @Test @@ -1223,6 +1226,49 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest verify(task2, never()).onExclusionRegionChanged(newRegion) } + @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX) + fun testRecentsTransitionStateListener_requestedState_setsTransitionRunning() { + val task = createTask(windowingMode = WINDOWING_MODE_FREEFORM) + val decoration = setUpMockDecorationForTask(task) + onTaskOpening(task, SurfaceControl()) + + desktopModeRecentsTransitionStateListener.onTransitionStateChanged( + RecentsTransitionStateListener.TRANSITION_STATE_REQUESTED) + + verify(decoration).setIsRecentsTransitionRunning(true) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX) + fun testRecentsTransitionStateListener_nonRunningState_setsTransitionNotRunning() { + val task = createTask(windowingMode = WINDOWING_MODE_FREEFORM) + val decoration = setUpMockDecorationForTask(task) + onTaskOpening(task, SurfaceControl()) + desktopModeRecentsTransitionStateListener.onTransitionStateChanged( + RecentsTransitionStateListener.TRANSITION_STATE_REQUESTED) + + desktopModeRecentsTransitionStateListener.onTransitionStateChanged( + RecentsTransitionStateListener.TRANSITION_STATE_NOT_RUNNING) + + verify(decoration).setIsRecentsTransitionRunning(false) + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX) + fun testRecentsTransitionStateListener_requestedAndAnimating_setsTransitionRunningOnce() { + val task = createTask(windowingMode = WINDOWING_MODE_FREEFORM) + val decoration = setUpMockDecorationForTask(task) + onTaskOpening(task, SurfaceControl()) + + desktopModeRecentsTransitionStateListener.onTransitionStateChanged( + RecentsTransitionStateListener.TRANSITION_STATE_REQUESTED) + desktopModeRecentsTransitionStateListener.onTransitionStateChanged( + RecentsTransitionStateListener.TRANSITION_STATE_ANIMATING) + + verify(decoration, times(1)).setIsRecentsTransitionRunning(true) + } + private fun createOpenTaskDecoration( @WindowingMode windowingMode: Int, taskSurface: SurfaceControl = SurfaceControl(), diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt index 40015eece15c..b44af4733fd2 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelTestsBase.kt @@ -40,6 +40,7 @@ import android.view.SurfaceControl import android.view.WindowInsets.Type.statusBars import com.android.dx.mockito.inline.extended.StaticMockitoSession import com.android.internal.jank.InteractionJankMonitor +import com.android.window.flags.Flags import com.android.wm.shell.RootTaskDisplayAreaOrganizer import com.android.wm.shell.ShellTaskOrganizer import com.android.wm.shell.ShellTestCase @@ -65,6 +66,8 @@ import com.android.wm.shell.desktopmode.WindowDecorCaptionHandleRepository import com.android.wm.shell.desktopmode.education.AppHandleEducationController import com.android.wm.shell.desktopmode.education.AppToWebEducationController import com.android.wm.shell.freeform.FreeformTaskTransitionStarter +import com.android.wm.shell.recents.RecentsTransitionHandler +import com.android.wm.shell.recents.RecentsTransitionStateListener import com.android.wm.shell.splitscreen.SplitScreenController import com.android.wm.shell.sysui.ShellCommandHandler import com.android.wm.shell.sysui.ShellController @@ -151,6 +154,7 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() { protected val mockFocusTransitionObserver = mock<FocusTransitionObserver>() protected val mockCaptionHandleRepository = mock<WindowDecorCaptionHandleRepository>() protected val mockDesktopRepository: DesktopRepository = mock<DesktopRepository>() + protected val mockRecentsTransitionHandler = mock<RecentsTransitionHandler>() protected val motionEvent = mock<MotionEvent>() val displayLayout = mock<DisplayLayout>() protected lateinit var spyContext: TestableContext @@ -164,6 +168,7 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() { protected lateinit var mockitoSession: StaticMockitoSession protected lateinit var shellInit: ShellInit internal lateinit var desktopModeOnInsetsChangedListener: DesktopModeOnInsetsChangedListener + protected lateinit var desktopModeRecentsTransitionStateListener: RecentsTransitionStateListener protected lateinit var displayChangingListener: DisplayChangeController.OnDisplayChangingListener internal lateinit var desktopModeOnKeyguardChangedListener: DesktopModeKeyguardChangeListener @@ -220,7 +225,8 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() { mockFocusTransitionObserver, desktopModeEventLogger, mock<DesktopModeUiEventLogger>(), - mock<WindowDecorTaskResourceLoader>() + mock<WindowDecorTaskResourceLoader>(), + mockRecentsTransitionHandler, ) desktopModeWindowDecorViewModel.setSplitScreenController(mockSplitScreenController) whenever(mockDisplayController.getDisplayLayout(any())).thenReturn(mockDisplayLayout) @@ -257,6 +263,13 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() { verify(displayInsetsController) .addGlobalInsetsChangedListener(insetsChangedCaptor.capture()) desktopModeOnInsetsChangedListener = insetsChangedCaptor.firstValue + val recentsTransitionStateListenerCaptor = argumentCaptor<RecentsTransitionStateListener>() + if (Flags.enableDesktopRecentsTransitionsCornersBugfix()) { + verify(mockRecentsTransitionHandler) + .addTransitionStateListener(recentsTransitionStateListenerCaptor.capture()) + desktopModeRecentsTransitionStateListener = + recentsTransitionStateListenerCaptor.firstValue + } val keyguardChangedCaptor = argumentCaptor<DesktopModeKeyguardChangeListener>() verify(mockShellController).addKeyguardChangeListener(keyguardChangedCaptor.capture()) diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java index 6b02aeffd42a..9ea5fd6e1abe 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java @@ -169,6 +169,7 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { private static final boolean DEFAULT_IS_KEYGUARD_VISIBLE_AND_OCCLUDED = false; private static final boolean DEFAULT_IS_IN_FULL_IMMERSIVE_MODE = false; private static final boolean DEFAULT_HAS_GLOBAL_FOCUS = true; + private static final boolean DEFAULT_SHOULD_IGNORE_CORNER_RADIUS = false; @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT); @@ -396,6 +397,31 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { } @Test + public void updateRelayoutParams_shouldIgnoreCornerRadius_roundedCornersNotSet() { + final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); + taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM); + fillRoundedCornersResources(/* fillValue= */ 30); + RelayoutParams relayoutParams = new RelayoutParams(); + + DesktopModeWindowDecoration.updateRelayoutParams( + relayoutParams, + mTestableContext, + taskInfo, + mMockSplitScreenController, + DEFAULT_APPLY_START_TRANSACTION_ON_DRAW, + DEFAULT_SHOULD_SET_TASK_POSITIONING_AND_CROP, + DEFAULT_IS_STATUSBAR_VISIBLE, + DEFAULT_IS_KEYGUARD_VISIBLE_AND_OCCLUDED, + DEFAULT_IS_IN_FULL_IMMERSIVE_MODE, + new InsetsState(), + DEFAULT_HAS_GLOBAL_FOCUS, + mExclusionRegion, + /* shouldIgnoreCornerRadius= */ true); + + assertThat(relayoutParams.mCornerRadius).isEqualTo(INVALID_CORNER_RADIUS); + } + + @Test @EnableFlags(Flags.FLAG_ENABLE_APP_HEADER_WITH_TASK_DENSITY) public void updateRelayoutParams_appHeader_usesTaskDensity() { final int systemDensity = mTestableContext.getOrCreateTestableResources().getResources() @@ -634,7 +660,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { /* inFullImmersiveMode */ true, insetsState, DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion); + mExclusionRegion, + DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); // Takes status bar inset as padding, ignores caption bar inset. assertThat(relayoutParams.mCaptionTopPadding).isEqualTo(50); @@ -659,7 +686,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { /* inFullImmersiveMode */ true, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion); + mExclusionRegion, + DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); assertThat(relayoutParams.mIsInsetSource).isFalse(); } @@ -683,7 +711,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_IS_IN_FULL_IMMERSIVE_MODE, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion); + mExclusionRegion, + DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); // Header is always shown because it's assumed the status bar is always visible. assertThat(relayoutParams.mIsCaptionVisible).isTrue(); @@ -707,7 +736,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_IS_IN_FULL_IMMERSIVE_MODE, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion); + mExclusionRegion, + DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); assertThat(relayoutParams.mIsCaptionVisible).isTrue(); } @@ -730,7 +760,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_IS_IN_FULL_IMMERSIVE_MODE, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion); + mExclusionRegion, + DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); assertThat(relayoutParams.mIsCaptionVisible).isFalse(); } @@ -753,7 +784,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_IS_IN_FULL_IMMERSIVE_MODE, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion); + mExclusionRegion, + DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); assertThat(relayoutParams.mIsCaptionVisible).isFalse(); } @@ -777,7 +809,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { /* inFullImmersiveMode */ true, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion); + mExclusionRegion, + DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); assertThat(relayoutParams.mIsCaptionVisible).isTrue(); @@ -793,7 +826,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { /* inFullImmersiveMode */ true, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion); + mExclusionRegion, + DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); assertThat(relayoutParams.mIsCaptionVisible).isFalse(); } @@ -817,7 +851,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { /* inFullImmersiveMode */ true, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion); + mExclusionRegion, + DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); assertThat(relayoutParams.mIsCaptionVisible).isFalse(); } @@ -1480,7 +1515,8 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_IS_IN_FULL_IMMERSIVE_MODE, new InsetsState(), DEFAULT_HAS_GLOBAL_FOCUS, - mExclusionRegion); + mExclusionRegion, + DEFAULT_SHOULD_IGNORE_CORNER_RADIUS); } private DesktopModeWindowDecoration createWindowDecoration( diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java index 51892aac606a..ff6bcdb150f8 100644 --- a/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java +++ b/packages/SystemUI/shared/src/com/android/systemui/shared/system/RecentsAnimationListener.java @@ -19,6 +19,7 @@ package com.android.systemui.shared.system; import android.graphics.Rect; import android.os.Bundle; import android.view.RemoteAnimationTarget; +import android.window.TransitionInfo; import com.android.systemui.shared.recents.model.ThumbnailData; @@ -30,7 +31,7 @@ public interface RecentsAnimationListener { */ void onAnimationStart(RecentsAnimationControllerCompat controller, RemoteAnimationTarget[] apps, RemoteAnimationTarget[] wallpapers, - Rect homeContentInsets, Rect minimizedHomeBounds, Bundle extras); + Rect homeContentInsets, Rect minimizedHomeBounds, Bundle extras, TransitionInfo info); /** * Called when the animation into Recents was canceled. This call is made on the binder thread. |