diff options
author | 2024-12-03 18:07:21 -0800 | |
---|---|---|
committer | 2025-03-11 00:21:27 +0000 | |
commit | 1eaeaadc3c723a1d47555dfe4b86f72663f77c6c (patch) | |
tree | eaa4f3e865b6bb89f2fe24c59ad23d6c2356b1f2 | |
parent | 5d4bc924e4317b1b519c69fef1d69a769ef38747 (diff) |
Tighten requirements for status bar input layer.
Adds split select tracking logic to DesktopModeWindowDecoration. Uses this and the existing recents tracking to determine whether or not the status bar input layer should show.
Bug: 371473978
Test: Manual
Flag: com.android.window.flags.enable_handle_input_fix
Flag: com.android.window.flags.enable_input_layer_transition_fix
Change-Id: I015d6cc0e9a857ed16d749e552a1eabe181f66b5
12 files changed, 268 insertions, 92 deletions
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java index f89ba0a168d1..0bf2ea61b0a4 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/freeform/FreeformTaskTransitionObserver.java @@ -174,7 +174,7 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs SurfaceControl.Transaction finishT) { mTaskChangeListener.ifPresent(listener -> listener.onTaskChanging(change.getTaskInfo())); mWindowDecorViewModel.onTaskChanging( - change.getTaskInfo(), change.getLeash(), startT, finishT); + change.getTaskInfo(), change.getLeash(), startT, finishT, change.getMode()); } private void onToFrontTransitionReady( @@ -184,7 +184,7 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs mTaskChangeListener.ifPresent( listener -> listener.onTaskMovingToFront(change.getTaskInfo())); mWindowDecorViewModel.onTaskChanging( - change.getTaskInfo(), change.getLeash(), startT, finishT); + change.getTaskInfo(), change.getLeash(), startT, finishT, change.getMode()); } private void onToBackTransitionReady( @@ -194,7 +194,7 @@ public class FreeformTaskTransitionObserver implements Transitions.TransitionObs mTaskChangeListener.ifPresent( listener -> listener.onTaskMovingToBack(change.getTaskInfo())); mWindowDecorViewModel.onTaskChanging( - change.getTaskInfo(), change.getLeash(), startT, finishT); + change.getTaskInfo(), change.getLeash(), startT, finishT, change.getMode()); } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 75c09829e551..a7cba76ea91f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -123,6 +123,7 @@ import android.view.SurfaceControl; import android.view.WindowManager; import android.widget.Toast; import android.window.DesktopExperienceFlags; +import android.window.DesktopModeFlags; import android.window.DisplayAreaInfo; import android.window.RemoteTransition; import android.window.TransitionInfo; @@ -675,7 +676,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, if (!enteredSplitSelect) { return null; } - if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue()) { + if (!DesktopExperienceFlags.ENABLE_MULTIPLE_DESKTOPS_BACKEND.isTrue() + && !DesktopModeFlags.ENABLE_INPUT_LAYER_TRANSITION_FIX.isTrue()) { mTaskOrganizer.applyTransaction(wct); return null; } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java index 7871179a50de..42321e56e72b 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CaptionWindowDecorViewModel.java @@ -49,6 +49,7 @@ import android.view.SurfaceControl; import android.view.View; import android.view.ViewConfiguration; import android.window.DisplayAreaInfo; +import android.window.TransitionInfo; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; @@ -233,7 +234,8 @@ public class CaptionWindowDecorViewModel implements WindowDecorViewModel, FocusT RunningTaskInfo taskInfo, SurfaceControl taskSurface, SurfaceControl.Transaction startT, - SurfaceControl.Transaction finishT) { + SurfaceControl.Transaction finishT, + @TransitionInfo.TransitionMode int changeMode) { final CaptionWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId); if (!shouldShowWindowDecor(taskInfo)) { diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecorViewModel.java index 2b2cdf84005c..4511fbe10764 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecorViewModel.java @@ -31,6 +31,7 @@ import android.view.KeyCharacterMap; import android.view.KeyEvent; import android.view.SurfaceControl; import android.view.View; +import android.window.TransitionInfo; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; @@ -159,7 +160,8 @@ public abstract class CarWindowDecorViewModel RunningTaskInfo taskInfo, SurfaceControl taskSurface, SurfaceControl.Transaction startT, - SurfaceControl.Transaction finishT) { + SurfaceControl.Transaction finishT, + @TransitionInfo.TransitionMode int changeMode) { final CarWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId); if (!shouldShowWindowDecor(taskInfo)) { 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 a1d2774ee428..c9ae20091a7e 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 @@ -27,6 +27,7 @@ import static android.view.MotionEvent.ACTION_HOVER_EXIT; import static android.view.MotionEvent.ACTION_MOVE; import static android.view.MotionEvent.ACTION_UP; import static android.view.WindowInsets.Type.statusBars; +import static android.view.WindowManager.TRANSIT_TO_BACK; import static com.android.internal.jank.Cuj.CUJ_DESKTOP_MODE_ENTER_MODE_APP_HANDLE_MENU; import static com.android.window.flags.Flags.enableDisplayFocusInShellTransitions; @@ -79,6 +80,7 @@ import android.view.ViewConfiguration; import android.view.ViewRootImpl; import android.window.DesktopModeFlags; import android.window.TaskSnapshot; +import android.window.TransitionInfo; import android.window.WindowContainerToken; import android.window.WindowContainerTransaction; @@ -150,18 +152,19 @@ import com.android.wm.shell.windowdecor.extension.InsetsStateKt; import com.android.wm.shell.windowdecor.extension.TaskInfoKt; import com.android.wm.shell.windowdecor.tiling.DesktopTilingDecorViewModel; import com.android.wm.shell.windowdecor.tiling.SnapEventHandler; +import com.android.wm.shell.windowdecor.viewholder.AppHandleViewHolder; import com.android.wm.shell.windowdecor.viewholder.AppHeaderViewHolder; import kotlin.Pair; import kotlin.Unit; import kotlin.jvm.functions.Function1; -import org.jetbrains.annotations.NotNull; - import kotlinx.coroutines.CoroutineScope; import kotlinx.coroutines.ExperimentalCoroutinesApi; import kotlinx.coroutines.MainCoroutineDispatcher; +import org.jetbrains.annotations.NotNull; + import java.io.PrintWriter; import java.util.ArrayList; import java.util.HashSet; @@ -206,6 +209,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, private final AppToWebEducationController mAppToWebEducationController; private final AppHandleAndHeaderVisibilityHelper mAppHandleAndHeaderVisibilityHelper; private final AppHeaderViewHolder.Factory mAppHeaderViewHolderFactory; + private final AppHandleViewHolder.Factory mAppHandleViewHolderFactory; private boolean mTransitionDragActive; private SparseArray<EventReceiver> mEventReceiversByDisplay = new SparseArray<>(); @@ -331,6 +335,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, new InputMonitorFactory(), SurfaceControl.Transaction::new, new AppHeaderViewHolder.Factory(), + new AppHandleViewHolder.Factory(), rootTaskDisplayAreaOrganizer, new SparseArray<>(), interactionJankMonitor, @@ -380,6 +385,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, InputMonitorFactory inputMonitorFactory, Supplier<SurfaceControl.Transaction> transactionFactory, AppHeaderViewHolder.Factory appHeaderViewHolderFactory, + AppHandleViewHolder.Factory appHandleViewHolderFactory, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, SparseArray<DesktopModeWindowDecoration> windowDecorByTaskId, InteractionJankMonitor interactionJankMonitor, @@ -422,6 +428,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, mInputMonitorFactory = inputMonitorFactory; mTransactionFactory = transactionFactory; mAppHeaderViewHolderFactory = appHeaderViewHolderFactory; + mAppHandleViewHolderFactory = appHandleViewHolderFactory; mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer; mGenericLinksParser = genericLinksParser; mInputManager = mContext.getSystemService(InputManager.class); @@ -486,7 +493,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, new DesktopModeOnTaskResizeAnimationListener()); mDesktopTasksController.setOnTaskRepositionAnimationListener( new DesktopModeOnTaskRepositionAnimationListener()); - if (DesktopModeFlags.ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX.isTrue()) { + if (DesktopModeFlags.ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX.isTrue() + || DesktopModeFlags.ENABLE_INPUT_LAYER_TRANSITION_FIX.isTrue()) { mRecentsTransitionHandler.addTransitionStateListener( new DesktopModeRecentsTransitionStateListener()); } @@ -587,7 +595,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, RunningTaskInfo taskInfo, SurfaceControl taskSurface, SurfaceControl.Transaction startT, - SurfaceControl.Transaction finishT) { + SurfaceControl.Transaction finishT, + @TransitionInfo.TransitionMode int changeMode) { final DesktopModeWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId); if (!shouldShowWindowDecor(taskInfo)) { if (decoration != null) { @@ -601,8 +610,8 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, } else { decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */, false /* shouldSetTaskPositionAndCrop */, - mFocusTransitionObserver.hasGlobalFocus(taskInfo), - mExclusionRegion); + mFocusTransitionObserver.hasGlobalFocus(taskInfo), mExclusionRegion, + /*isMovingToBack= */ changeMode == TRANSIT_TO_BACK); } } @@ -617,7 +626,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, decoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */, false /* shouldSetTaskPositionAndCrop */, mFocusTransitionObserver.hasGlobalFocus(taskInfo), - mExclusionRegion); + mExclusionRegion, /* isMovingToBack= */ false); } @Override @@ -817,9 +826,6 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, return; } decoration.closeHandleMenu(); - // When the app enters split-select, the handle will no longer be visible, meaning - // we shouldn't receive input for it any longer. - decoration.disposeStatusBarInputLayer(); mDesktopTasksController.requestSplit(decoration.mTaskInfo, false /* leftOrTop */); mDesktopModeUiEventLogger.log(decoration.mTaskInfo, DesktopUiEventEnum.DESKTOP_WINDOW_APP_HANDLE_MENU_TAP_TO_SPLIT_SCREEN); @@ -1761,6 +1767,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, mMainChoreographer, mSyncQueue, mAppHeaderViewHolderFactory, + mAppHandleViewHolderFactory, mRootTaskDisplayAreaOrganizer, mGenericLinksParser, mAssistContentRequester, @@ -1852,12 +1859,13 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel, windowDecoration.relayout(taskInfo, startT, finishT, false /* applyStartTransactionOnDraw */, false /* shouldSetTaskPositionAndCrop */, mFocusTransitionObserver.hasGlobalFocus(taskInfo), - mExclusionRegion); + mExclusionRegion, /* isMovingToBack= */ false); if (!DesktopModeFlags.ENABLE_HANDLE_INPUT_FIX.isTrue()) { incrementEventReceiverTasks(taskInfo.displayId); } } + @Nullable private RunningTaskInfo getOtherSplitTask(int taskId) { @SplitPosition int remainingTaskPosition = mSplitScreenController .getSplitPosition(taskId) == SPLIT_POSITION_BOTTOM_OR_RIGHT 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 bd21f8db122d..8f48abdd4288 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 @@ -190,6 +190,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin private ExclusionRegionListener mExclusionRegionListener; private final AppHeaderViewHolder.Factory mAppHeaderViewHolderFactory; + private final AppHandleViewHolder.Factory mAppHandleViewHolderFactory; private final RootTaskDisplayAreaOrganizer mRootTaskDisplayAreaOrganizer; private final MaximizeMenuFactory mMaximizeMenuFactory; private final HandleMenuFactory mHandleMenuFactory; @@ -212,6 +213,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin private boolean mIsDragging = false; private Runnable mLoadAppInfoRunnable; private Runnable mSetAppInfoRunnable; + private boolean mIsMovingToBack; public DesktopModeWindowDecoration( Context context, @@ -231,6 +233,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin Choreographer choreographer, SyncTransactionQueue syncQueue, AppHeaderViewHolder.Factory appHeaderViewHolderFactory, + AppHandleViewHolder.Factory appHandleViewHolderFactory, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, AppToWebGenericLinksParser genericLinksParser, AssistContentRequester assistContentRequester, @@ -242,10 +245,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin this (context, userContext, displayController, taskResourceLoader, splitScreenController, desktopUserRepositories, taskOrganizer, taskInfo, taskSurface, handler, mainExecutor, mainDispatcher, bgScope, bgExecutor, choreographer, syncQueue, - appHeaderViewHolderFactory, rootTaskDisplayAreaOrganizer, genericLinksParser, - assistContentRequester, SurfaceControl.Builder::new, - SurfaceControl.Transaction::new, WindowContainerTransaction::new, - SurfaceControl::new, new WindowManagerWrapper( + appHeaderViewHolderFactory, appHandleViewHolderFactory, + rootTaskDisplayAreaOrganizer, genericLinksParser, assistContentRequester, + SurfaceControl.Builder::new, SurfaceControl.Transaction::new, + WindowContainerTransaction::new, SurfaceControl::new, new WindowManagerWrapper( context.getSystemService(WindowManager.class)), new SurfaceControlViewHostFactory() {}, windowDecorViewHostSupplier, @@ -273,6 +276,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin Choreographer choreographer, SyncTransactionQueue syncQueue, AppHeaderViewHolder.Factory appHeaderViewHolderFactory, + AppHandleViewHolder.Factory appHandleViewHolderFactory, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, AppToWebGenericLinksParser genericLinksParser, AssistContentRequester assistContentRequester, @@ -302,6 +306,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin mChoreographer = choreographer; mSyncQueue = syncQueue; mAppHeaderViewHolderFactory = appHeaderViewHolderFactory; + mAppHandleViewHolderFactory = appHandleViewHolderFactory; mRootTaskDisplayAreaOrganizer = rootTaskDisplayAreaOrganizer; mGenericLinksParser = genericLinksParser; mAssistContentRequester = assistContentRequester; @@ -462,7 +467,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin // causes flickering. See b/270202228. final boolean applyTransactionOnDraw = taskInfo.isFreeform(); relayout(taskInfo, t, t, applyTransactionOnDraw, shouldSetTaskVisibilityPositionAndCrop, - hasGlobalFocus, displayExclusionRegion); + hasGlobalFocus, displayExclusionRegion, mIsMovingToBack); if (!applyTransactionOnDraw) { t.apply(); } @@ -489,7 +494,8 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin void relayout(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT, boolean applyStartTransactionOnDraw, boolean shouldSetTaskVisibilityPositionAndCrop, - boolean hasGlobalFocus, @NonNull Region displayExclusionRegion) { + boolean hasGlobalFocus, @NonNull Region displayExclusionRegion, + boolean isMovingToBack) { Trace.beginSection("DesktopModeWindowDecoration#relayout"); if (DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_APP_TO_WEB.isTrue()) { @@ -512,12 +518,17 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin final boolean inFullImmersive = mDesktopUserRepositories.getProfile(taskInfo.userId) .isTaskInFullImmersiveState(taskInfo.taskId); + mIsMovingToBack = isMovingToBack; updateRelayoutParams(mRelayoutParams, mContext, taskInfo, mSplitScreenController, applyStartTransactionOnDraw, shouldSetTaskVisibilityPositionAndCrop, mIsStatusBarVisible, mIsKeyguardVisibleAndOccluded, inFullImmersive, mIsDragging, mDisplayController.getInsetsState(taskInfo.displayId), hasGlobalFocus, - displayExclusionRegion, mIsRecentsTransitionRunning, - mDesktopModeCompatPolicy.shouldExcludeCaptionFromAppBounds(taskInfo)); + displayExclusionRegion, + /* shouldIgnoreCornerRadius= */ mIsRecentsTransitionRunning + && DesktopModeFlags + .ENABLE_DESKTOP_RECENTS_TRANSITIONS_CORNERS_BUGFIX.isTrue(), + mDesktopModeCompatPolicy.shouldExcludeCaptionFromAppBounds(taskInfo), + mIsRecentsTransitionRunning, mIsMovingToBack); final WindowDecorLinearLayout oldRootView = mResult.mRootView; final SurfaceControl oldDecorationSurface = mDecorationContainerSurface; @@ -558,29 +569,15 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin }); } - final Point position = new Point(); - if (isAppHandle(mWindowDecorViewHolder)) { - position.set(determineHandlePosition()); - } if (canEnterDesktopMode(mContext) && isEducationEnabled()) { notifyCaptionStateChanged(); } Trace.beginSection("DesktopModeWindowDecoration#relayout-bindData"); if (isAppHandle(mWindowDecorViewHolder)) { - mWindowDecorViewHolder.bindData(new AppHandleViewHolder.HandleData( - mTaskInfo, position, mResult.mCaptionWidth, mResult.mCaptionHeight, - isCaptionVisible() - )); + updateAppHandleViewHolder(); } else { - mWindowDecorViewHolder.bindData(new AppHeaderViewHolder.HeaderData( - mTaskInfo, - DesktopModeUtils.isTaskMaximized(mTaskInfo, mDisplayController), - inFullImmersive, - hasGlobalFocus, - /* maximizeHoverEnabled= */ canOpenMaximizeMenu( - /* animatingTaskResizeOrReposition= */ false) - )); + updateAppHeaderViewHolder(inFullImmersive, hasGlobalFocus); } Trace.endSection(); @@ -857,9 +854,31 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin asAppHandle(mWindowDecorViewHolder).disposeStatusBarInputLayer(); } + /** Update the view holder for app handle. */ + private void updateAppHandleViewHolder() { + if (!isAppHandle(mWindowDecorViewHolder)) return; + asAppHandle(mWindowDecorViewHolder).bindData(new AppHandleViewHolder.HandleData( + mTaskInfo, determineHandlePosition(), mResult.mCaptionWidth, + mResult.mCaptionHeight, isCaptionVisible() + )); + } + + /** Update the view holder for app header. */ + private void updateAppHeaderViewHolder(boolean inFullImmersive, boolean hasGlobalFocus) { + if (!isAppHeader(mWindowDecorViewHolder)) return; + asAppHeader(mWindowDecorViewHolder).bindData(new AppHeaderViewHolder.HeaderData( + mTaskInfo, + DesktopModeUtils.isTaskMaximized(mTaskInfo, mDisplayController), + inFullImmersive, + hasGlobalFocus, + /* maximizeHoverEnabled= */ canOpenMaximizeMenu( + /* animatingTaskResizeOrReposition= */ false) + )); + } + private WindowDecorationViewHolder createViewHolder() { if (mRelayoutParams.mLayoutResId == R.layout.desktop_mode_app_handle) { - return new AppHandleViewHolder( + return mAppHandleViewHolderFactory.create( mResult.mRootView, mOnCaptionTouchListener, mOnCaptionButtonClickListener, @@ -886,6 +905,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin return viewHolder instanceof AppHandleViewHolder; } + private boolean isAppHeader(WindowDecorationViewHolder viewHolder) { + return viewHolder instanceof AppHeaderViewHolder; + } + @Nullable private AppHandleViewHolder asAppHandle(WindowDecorationViewHolder viewHolder) { if (viewHolder instanceof AppHandleViewHolder) { @@ -918,7 +941,9 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin boolean hasGlobalFocus, @NonNull Region displayExclusionRegion, boolean shouldIgnoreCornerRadius, - boolean shouldExcludeCaptionFromAppBounds) { + boolean shouldExcludeCaptionFromAppBounds, + boolean isRecentsTransitionRunning, + boolean isMovingToBack) { final int captionLayoutId = getDesktopModeWindowDecorLayoutId(taskInfo.getWindowingMode()); final boolean isAppHeader = captionLayoutId == R.layout.desktop_mode_app_header; @@ -935,11 +960,20 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin // the first frame. relayoutParams.mAsyncViewHost = isAppHandle; - final boolean showCaption; - if (DesktopModeFlags.ENABLE_DESKTOP_IMMERSIVE_DRAG_BUGFIX.isTrue() && isDragging) { + boolean showCaption; + // If this relayout is occurring from an observed TRANSIT_TO_BACK transition, do not + // show caption (this includes split select transition). + if (DesktopModeFlags.ENABLE_INPUT_LAYER_TRANSITION_FIX.isTrue() + && isMovingToBack && !isDragging) { + showCaption = false; + } else if (DesktopModeFlags.ENABLE_DESKTOP_IMMERSIVE_DRAG_BUGFIX.isTrue() && isDragging) { // If the task is being dragged, the caption should not be hidden so that it continues // receiving input showCaption = true; + } else if (DesktopModeFlags.ENABLE_INPUT_LAYER_TRANSITION_FIX.isTrue() + && isRecentsTransitionRunning) { + // Caption should not be visible in recents. + showCaption = false; } else if (DesktopModeFlags.ENABLE_FULLY_IMMERSIVE_IN_DESKTOP.isTrue()) { if (inFullImmersiveMode) { showCaption = (isStatusBarVisible && !isKeyguardVisibleAndOccluded); @@ -1800,9 +1834,18 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin * <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. + * + * We should not allow input to reach the input layer during a Recents transition, so + * update the handle view holder accordingly if transition status changes. */ void setIsRecentsTransitionRunning(boolean isRecentsTransitionRunning) { - mIsRecentsTransitionRunning = isRecentsTransitionRunning; + if (mIsRecentsTransitionRunning != isRecentsTransitionRunning) { + mIsRecentsTransitionRunning = isRecentsTransitionRunning; + if (DesktopModeFlags.ENABLE_INPUT_LAYER_TRANSITION_FIX.isTrue()) { + // We don't relayout decor on recents transition, so we need to call it directly. + relayout(mTaskInfo, mHasGlobalFocus, mRelayoutParams.mDisplayExclusionRegion); + } + } } /** @@ -1867,6 +1910,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin Choreographer choreographer, SyncTransactionQueue syncQueue, AppHeaderViewHolder.Factory appHeaderViewHolderFactory, + AppHandleViewHolder.Factory appHandleViewHolderFactory, RootTaskDisplayAreaOrganizer rootTaskDisplayAreaOrganizer, AppToWebGenericLinksParser genericLinksParser, AssistContentRequester assistContentRequester, @@ -1894,6 +1938,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin choreographer, syncQueue, appHeaderViewHolderFactory, + appHandleViewHolderFactory, rootTaskDisplayAreaOrganizer, genericLinksParser, assistContentRequester, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java index 1563259f4a1a..5e4a0a5860f0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecorViewModel.java @@ -18,6 +18,7 @@ package com.android.wm.shell.windowdecor; import android.app.ActivityManager; import android.view.SurfaceControl; +import android.window.TransitionInfo; import com.android.wm.shell.freeform.FreeformTaskTransitionStarter; import com.android.wm.shell.splitscreen.SplitScreenController; @@ -83,12 +84,14 @@ public interface WindowDecorViewModel { * @param taskSurface the surface of the task * @param startT the start transaction to be applied before the transition * @param finishT the finish transaction to restore states after the transition + * @param changeMode the type of change to the task */ void onTaskChanging( ActivityManager.RunningTaskInfo taskInfo, SurfaceControl taskSurface, SurfaceControl.Transaction startT, - SurfaceControl.Transaction finishT); + SurfaceControl.Transaction finishT, + @TransitionInfo.TransitionMode int changeMode); /** * Notifies that the given task is about to close to give the window decoration a chance to diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt index d9df899f8b40..0985587a330e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/viewholder/AppHandleViewHolder.kt @@ -49,7 +49,7 @@ import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalSystem * A desktop mode window decoration used when the window is in full "focus" (i.e. fullscreen/split). * It hosts a simple handle bar from which to initiate a drag motion to enter desktop mode. */ -internal class AppHandleViewHolder( +class AppHandleViewHolder( rootView: View, onCaptionTouchListener: View.OnTouchListener, onCaptionButtonClickListener: OnClickListener, @@ -66,7 +66,7 @@ internal class AppHandleViewHolder( val position: Point, val width: Int, val height: Int, - val isCaptionVisible: Boolean + val showInputLayer: Boolean ) : Data() private lateinit var taskInfo: RunningTaskInfo @@ -101,7 +101,7 @@ internal class AppHandleViewHolder( } override fun bindData(data: HandleData) { - bindData(data.taskInfo, data.position, data.width, data.height, data.isCaptionVisible) + bindData(data.taskInfo, data.position, data.width, data.height, data.showInputLayer) } private fun bindData( @@ -109,14 +109,13 @@ internal class AppHandleViewHolder( position: Point, width: Int, height: Int, - isCaptionVisible: Boolean + showInputLayer: Boolean ) { captionHandle.imageTintList = ColorStateList.valueOf(getCaptionHandleBarColor(taskInfo)) this.taskInfo = taskInfo // If handle is not in status bar region(i.e., bottom stage in vertical split), // do not create an input layer - if (position.y >= SystemBarUtils.getStatusBarHeight(context)) return - if (!isCaptionVisible) { + if (position.y >= SystemBarUtils.getStatusBarHeight(context) || !showInputLayer) { disposeStatusBarInputLayer() return } @@ -276,4 +275,25 @@ internal class AppHandleViewHolder( } override fun close() {} + + /** Factory class for creating [AppHandleViewHolder] objects. */ + class Factory { + /** + * Create a [AppHandleViewHolder] object to handle caption view and status bar + * input layer logic. + */ + fun create( + rootView: View, + onCaptionTouchListener: View.OnTouchListener, + onCaptionButtonClickListener: OnClickListener, + windowManagerWrapper: WindowManagerWrapper, + handler: Handler, + ): AppHandleViewHolder = AppHandleViewHolder( + rootView, + onCaptionTouchListener, + onCaptionButtonClickListener, + windowManagerWrapper, + handler, + ) + } } diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelAppHandleOnlyTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelAppHandleOnlyTest.kt index 067dcec5d65d..b1f92411c5a3 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelAppHandleOnlyTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorViewModelAppHandleOnlyTest.kt @@ -28,6 +28,7 @@ import android.testing.TestableLooper.RunWithLooper import android.view.Display import android.view.Display.DEFAULT_DISPLAY import android.view.SurfaceControl +import android.view.WindowManager.TRANSIT_CHANGE import androidx.test.filters.SmallTest import com.android.dx.mockito.inline.extended.ExtendedMockito.anyBoolean import com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn @@ -109,7 +110,7 @@ class DesktopModeWindowDecorViewModelAppHandleOnlyTest : onTaskOpening(task, taskSurface) assertTrue(windowDecorByTaskIdSpy.contains(task.taskId)) task.setActivityType(ACTIVITY_TYPE_UNDEFINED) - onTaskChanging(task, taskSurface) + onTaskChanging(task, taskSurface, TRANSIT_CHANGE) assertFalse(windowDecorByTaskIdSpy.contains(task.taskId)) verify(decoration).close() @@ -165,7 +166,7 @@ class DesktopModeWindowDecorViewModelAppHandleOnlyTest : setLargeScreen(false) setUpMockDecorationForTask(task) - onTaskChanging(task, taskSurface) + onTaskChanging(task, taskSurface, TRANSIT_CHANGE) assertFalse(windowDecorByTaskIdSpy.contains(task.taskId)) } 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 d69509faf4ec..ad3426e82805 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 @@ -51,6 +51,7 @@ import android.view.SurfaceView import android.view.View import android.view.ViewRootImpl import android.view.WindowInsets.Type.statusBars +import android.view.WindowManager.TRANSIT_CHANGE import android.window.WindowContainerTransaction import android.window.WindowContainerTransaction.HierarchyOp import androidx.test.filters.SmallTest @@ -134,7 +135,7 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest task.setWindowingMode(WINDOWING_MODE_UNDEFINED) task.setActivityType(ACTIVITY_TYPE_UNDEFINED) - onTaskChanging(task, taskSurface) + onTaskChanging(task, taskSurface, TRANSIT_CHANGE) assertFalse(windowDecorByTaskIdSpy.contains(task.taskId)) verify(decoration).close() @@ -149,12 +150,12 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest val taskSurface = SurfaceControl() setUpMockDecorationForTask(task) - onTaskChanging(task, taskSurface) + onTaskChanging(task, taskSurface, TRANSIT_CHANGE) assertFalse(windowDecorByTaskIdSpy.contains(task.taskId)) task.setWindowingMode(WINDOWING_MODE_FREEFORM) task.setActivityType(ACTIVITY_TYPE_STANDARD) - onTaskChanging(task, taskSurface) + onTaskChanging(task, taskSurface, TRANSIT_CHANGE) assertTrue(windowDecorByTaskIdSpy.contains(task.taskId)) } @@ -758,20 +759,6 @@ class DesktopModeWindowDecorViewModelTests : DesktopModeWindowDecorViewModelTest } @Test - fun testDecor_onClickToSplitScreen_disposesStatusBarInputLayer() { - val toSplitScreenListenerCaptor = forClass(Function0::class.java) - as ArgumentCaptor<Function0<Unit>> - val decor = createOpenTaskDecoration( - windowingMode = WINDOWING_MODE_MULTI_WINDOW, - onToSplitScreenClickListenerCaptor = toSplitScreenListenerCaptor - ) - - toSplitScreenListenerCaptor.value.invoke() - - verify(decor).disposeStatusBarInputLayer() - } - - @Test fun testDecor_onClickToOpenBrowser_closeMenus() { val openInBrowserListenerCaptor = forClass(Consumer::class.java) as ArgumentCaptor<Consumer<Intent>> 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 a1f40fdefee9..4c9c2f14d805 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 @@ -84,6 +84,7 @@ import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHostSupplier import com.android.wm.shell.windowdecor.tiling.DesktopTilingDecorViewModel +import com.android.wm.shell.windowdecor.viewholder.AppHandleViewHolder import com.android.wm.shell.windowdecor.viewholder.AppHeaderViewHolder import org.junit.After import org.mockito.Mockito @@ -125,6 +126,7 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() { protected val mockShellController = mock<ShellController>() protected val testShellExecutor = TestShellExecutor() protected val mockAppHeaderViewHolderFactory = mock<AppHeaderViewHolder.Factory>() + protected val mockAppHandleViewHolderFactory = mock<AppHandleViewHolder.Factory>() protected val mockRootTaskDisplayAreaOrganizer = mock<RootTaskDisplayAreaOrganizer>() protected val mockShellCommandHandler = mock<ShellCommandHandler>() protected val mockWindowManager = mock<IWindowManager>() @@ -222,6 +224,7 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() { mockInputMonitorFactory, transactionFactory, mockAppHeaderViewHolderFactory, + mockAppHandleViewHolderFactory, mockRootTaskDisplayAreaOrganizer, windowDecorByTaskIdSpy, mockInteractionJankMonitor, @@ -331,7 +334,7 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() { mockDesktopModeWindowDecorFactory.create( any(), any(), any(), any(), any(), any(), any(), eq(task), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), any(), - any(), any(), any()) + any(), any(), any(), any()) ).thenReturn(decoration) decoration.mTaskInfo = task whenever(decoration.user).thenReturn(mockUserHandle) @@ -353,12 +356,17 @@ open class DesktopModeWindowDecorViewModelTestsBase : ShellTestCase() { ) } - protected fun onTaskChanging(task: RunningTaskInfo, leash: SurfaceControl = SurfaceControl()) { + protected fun onTaskChanging( + task: RunningTaskInfo, + leash: SurfaceControl = SurfaceControl(), + changeMode: Int + ) { desktopModeWindowDecorViewModel.onTaskChanging( task, leash, StubTransaction(), - StubTransaction() + StubTransaction(), + changeMode ) } 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 878324937f1a..f37f2fb14bea 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 @@ -115,6 +115,7 @@ import com.android.wm.shell.windowdecor.WindowDecoration.RelayoutParams; import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader; import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost; import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHostSupplier; +import com.android.wm.shell.windowdecor.viewholder.AppHandleViewHolder; import com.android.wm.shell.windowdecor.viewholder.AppHeaderViewHolder; import kotlin.Unit; @@ -171,6 +172,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { private static final boolean DEFAULT_HAS_GLOBAL_FOCUS = true; private static final boolean DEFAULT_SHOULD_IGNORE_CORNER_RADIUS = false; private static final boolean DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS = false; + private static final boolean DEFAULT_IS_RECENTS_TRANSITION_RUNNING = false; + private static final boolean DEFAULT_IS_MOVING_TO_BACK = false; + @Mock private DisplayController mMockDisplayController; @@ -191,8 +195,12 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { @Mock private AppHeaderViewHolder.Factory mMockAppHeaderViewHolderFactory; @Mock + private AppHandleViewHolder.Factory mMockAppHandleViewHolderFactory; + @Mock private AppHeaderViewHolder mMockAppHeaderViewHolder; @Mock + private AppHandleViewHolder mMockAppHandleViewHolder; + @Mock private RootTaskDisplayAreaOrganizer mMockRootTaskDisplayAreaOrganizer; @Mock private Supplier<SurfaceControl.Transaction> mMockTransactionSupplier; @@ -301,6 +309,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { when(mMockAppHeaderViewHolderFactory .create(any(), any(), any(), any(), any(), any(), any(), any(), any())) .thenReturn(mMockAppHeaderViewHolder); + when(mMockAppHandleViewHolderFactory + .create(any(), any(), any(), any(), any())) + .thenReturn(mMockAppHandleViewHolder); when(mMockDesktopUserRepositories.getCurrent()).thenReturn(mDesktopRepository); when(mMockDesktopUserRepositories.getProfile(anyInt())).thenReturn(mDesktopRepository); when(mMockWindowDecorViewHostSupplier.acquire(any(), eq(defaultDisplay))) @@ -421,7 +432,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_HAS_GLOBAL_FOCUS, mExclusionRegion, /* shouldIgnoreCornerRadius= */ true, - DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS); + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + DEFAULT_IS_MOVING_TO_BACK); assertThat(relayoutParams.mCornerRadius).isEqualTo(INVALID_CORNER_RADIUS); } @@ -623,7 +636,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_HAS_GLOBAL_FOCUS, mExclusionRegion, DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, - /* shouldExcludeCaptionFromAppBounds */ true); + /* shouldExcludeCaptionFromAppBounds */ true, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + DEFAULT_IS_MOVING_TO_BACK); // Force consuming flags are disabled. assertThat((relayoutParams.mInsetSourceFlags & FLAG_FORCE_CONSUMING) == 0).isTrue(); @@ -658,7 +673,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_HAS_GLOBAL_FOCUS, mExclusionRegion, DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, - DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS); + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + DEFAULT_IS_MOVING_TO_BACK); assertThat((relayoutParams.mInsetSourceFlags & FLAG_FORCE_CONSUMING) != 0).isTrue(); assertThat( @@ -737,7 +754,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_HAS_GLOBAL_FOCUS, mExclusionRegion, DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, - DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS); + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + DEFAULT_IS_MOVING_TO_BACK); // Takes status bar inset as padding, ignores caption bar inset. assertThat(relayoutParams.mCaptionTopPadding).isEqualTo(50); @@ -765,7 +784,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_HAS_GLOBAL_FOCUS, mExclusionRegion, DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, - DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS); + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + DEFAULT_IS_MOVING_TO_BACK); assertThat(relayoutParams.mIsInsetSource).isFalse(); } @@ -792,7 +813,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_HAS_GLOBAL_FOCUS, mExclusionRegion, DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, - DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS); + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + DEFAULT_IS_MOVING_TO_BACK); // Header is always shown because it's assumed the status bar is always visible. assertThat(relayoutParams.mIsCaptionVisible).isTrue(); @@ -819,7 +842,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_HAS_GLOBAL_FOCUS, mExclusionRegion, DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, - DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS); + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + DEFAULT_IS_MOVING_TO_BACK); assertThat(relayoutParams.mIsCaptionVisible).isTrue(); } @@ -845,7 +870,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_HAS_GLOBAL_FOCUS, mExclusionRegion, DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, - DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS); + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + DEFAULT_IS_MOVING_TO_BACK); assertThat(relayoutParams.mIsCaptionVisible).isFalse(); } @@ -871,7 +898,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_HAS_GLOBAL_FOCUS, mExclusionRegion, DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, - DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS); + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + DEFAULT_IS_MOVING_TO_BACK); assertThat(relayoutParams.mIsCaptionVisible).isFalse(); } @@ -898,7 +927,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_HAS_GLOBAL_FOCUS, mExclusionRegion, DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, - DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS); + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + DEFAULT_IS_MOVING_TO_BACK); assertThat(relayoutParams.mIsCaptionVisible).isTrue(); @@ -917,7 +948,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_HAS_GLOBAL_FOCUS, mExclusionRegion, DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, - DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS); + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + DEFAULT_IS_MOVING_TO_BACK); assertThat(relayoutParams.mIsCaptionVisible).isFalse(); } @@ -944,7 +977,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_HAS_GLOBAL_FOCUS, mExclusionRegion, DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, - DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS); + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + DEFAULT_IS_MOVING_TO_BACK); assertThat(relayoutParams.mIsCaptionVisible).isTrue(); } @@ -971,7 +1006,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_HAS_GLOBAL_FOCUS, mExclusionRegion, DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, - DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS); + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + DEFAULT_IS_MOVING_TO_BACK); assertThat(relayoutParams.mIsCaptionVisible).isFalse(); } @@ -1002,6 +1039,65 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { assertThat(relayoutParams.mAsyncViewHost).isFalse(); } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_INPUT_LAYER_TRANSITION_FIX) + public void updateRelayoutParams_handle_movingToBack_captionNotVisible() { + final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); + taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + final 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, + DEFAULT_IS_DRAGGING, + new InsetsState(), + DEFAULT_HAS_GLOBAL_FOCUS, + mExclusionRegion, + DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + /* isMovingToBack= */ true); + + assertThat(relayoutParams.mIsCaptionVisible).isFalse(); + } + + @Test + @EnableFlags(Flags.FLAG_ENABLE_INPUT_LAYER_TRANSITION_FIX) + public void updateRelayoutParams_handle_inRecentsTransition_captionNotVisible() { + final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); + taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FULLSCREEN); + final 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, + DEFAULT_IS_DRAGGING, + new InsetsState(), + DEFAULT_HAS_GLOBAL_FOCUS, + mExclusionRegion, + DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + /* isRecentsTransitionRunning= */ true, + DEFAULT_IS_MOVING_TO_BACK); + + assertThat(relayoutParams.mIsCaptionVisible).isFalse(); + } + @Test public void relayout_fullscreenTask_appliesTransactionImmediately() { final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); @@ -1633,7 +1729,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { DEFAULT_HAS_GLOBAL_FOCUS, mExclusionRegion, DEFAULT_SHOULD_IGNORE_CORNER_RADIUS, - DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS); + DEFAULT_SHOULD_EXCLUDE_CAPTION_FROM_APP_BOUNDS, + DEFAULT_IS_RECENTS_TRANSITION_RUNNING, + DEFAULT_IS_MOVING_TO_BACK); } private DesktopModeWindowDecoration createWindowDecoration( @@ -1676,9 +1774,9 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase { taskInfo, mMockSurfaceControl, mMockHandler, mMainExecutor, mMockMainCoroutineDispatcher, mMockBgCoroutineScope, mBgExecutor, mMockChoreographer, mMockSyncQueue, mMockAppHeaderViewHolderFactory, - mMockRootTaskDisplayAreaOrganizer, mMockGenericLinksParser, - mMockAssistContentRequester, SurfaceControl.Builder::new, mMockTransactionSupplier, - WindowContainerTransaction::new, SurfaceControl::new, + mMockAppHandleViewHolderFactory, mMockRootTaskDisplayAreaOrganizer, + mMockGenericLinksParser, mMockAssistContentRequester, SurfaceControl.Builder::new, + mMockTransactionSupplier, WindowContainerTransaction::new, SurfaceControl::new, new WindowManagerWrapper(mMockWindowManager), mMockSurfaceControlViewHostFactory, mMockWindowDecorViewHostSupplier, maximizeMenuFactory, mMockHandleMenuFactory, mMockMultiInstanceHelper, mMockCaptionHandleRepository, mDesktopModeEventLogger, |