diff options
8 files changed, 353 insertions, 88 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 2f506434ba90..aa42c673076c 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 @@ -59,6 +59,7 @@ import com.android.wm.shell.common.TaskStackListenerImpl; import com.android.wm.shell.dagger.back.ShellBackAnimationModule; import com.android.wm.shell.dagger.pip.PipModule; import com.android.wm.shell.desktopmode.DefaultDragToDesktopTransitionHandler; +import com.android.wm.shell.desktopmode.DesktopModeDragAndDropTransitionHandler; import com.android.wm.shell.desktopmode.DesktopModeEventLogger; import com.android.wm.shell.desktopmode.DesktopModeLoggerTransitionObserver; import com.android.wm.shell.desktopmode.DesktopModeTaskRepository; @@ -558,6 +559,7 @@ public abstract class WMShellModule { ReturnToDragStartAnimator returnToDragStartAnimator, EnterDesktopTaskTransitionHandler enterDesktopTransitionHandler, ExitDesktopTaskTransitionHandler exitDesktopTransitionHandler, + DesktopModeDragAndDropTransitionHandler desktopModeDragAndDropTransitionHandler, ToggleResizeDesktopTaskTransitionHandler toggleResizeDesktopTaskTransitionHandler, DragToDesktopTransitionHandler dragToDesktopTransitionHandler, @DynamicOverride DesktopModeTaskRepository desktopModeTaskRepository, @@ -573,7 +575,8 @@ public abstract class WMShellModule { displayController, shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer, dragAndDropController, transitions, keyguardManager, returnToDragStartAnimator, enterDesktopTransitionHandler, - exitDesktopTransitionHandler, toggleResizeDesktopTaskTransitionHandler, + exitDesktopTransitionHandler, desktopModeDragAndDropTransitionHandler, + toggleResizeDesktopTaskTransitionHandler, dragToDesktopTransitionHandler, desktopModeTaskRepository, desktopModeLoggerTransitionObserver, launchAdjacentController, recentsTransitionHandler, multiInstanceHelper, mainExecutor, desktopTasksLimiter, @@ -655,6 +658,14 @@ public abstract class WMShellModule { @WMSingleton @Provides + static DesktopModeDragAndDropTransitionHandler provideDesktopModeDragAndDropTransitionHandler( + Transitions transitions + ) { + return new DesktopModeDragAndDropTransitionHandler(transitions); + } + + @WMSingleton + @Provides @DynamicOverride static DesktopModeTaskRepository provideDesktopModeTaskRepository() { return new DesktopModeTaskRepository(); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeDragAndDropTransitionHandler.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeDragAndDropTransitionHandler.kt new file mode 100644 index 000000000000..a7a4a1036b5d --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeDragAndDropTransitionHandler.kt @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.wm.shell.desktopmode + +import android.animation.Animator +import android.animation.AnimatorListenerAdapter +import android.animation.ValueAnimator +import android.os.IBinder +import android.view.SurfaceControl +import android.view.WindowManager.TRANSIT_OPEN +import android.window.TransitionInfo +import android.window.TransitionRequestInfo +import android.window.WindowContainerTransaction +import com.android.wm.shell.transition.Transitions +import com.android.wm.shell.transition.Transitions.TransitionFinishCallback + +/** + * Transition handler for drag-and-drop (i.e., tab tear) transitions that occur in desktop mode. + */ +class DesktopModeDragAndDropTransitionHandler(private val transitions: Transitions) : + Transitions.TransitionHandler { + private val pendingTransitionTokens: MutableList<IBinder> = mutableListOf() + + /** + * Begin a transition when a [android.app.PendingIntent] is dropped without a window to + * accept it. + */ + fun handleDropEvent(wct: WindowContainerTransaction): IBinder { + val token = transitions.startTransition(TRANSIT_OPEN, wct, this) + pendingTransitionTokens.add(token) + return token + } + + override fun startAnimation( + transition: IBinder, + info: TransitionInfo, + startTransaction: SurfaceControl.Transaction, + finishTransaction: SurfaceControl.Transaction, + finishCallback: TransitionFinishCallback + ): Boolean { + if (!pendingTransitionTokens.contains(transition)) return false + val change = findRelevantChange(info) + val leash = change.leash + val endBounds = change.endAbsBounds + startTransaction.hide(leash) + .setWindowCrop(leash, endBounds.width(), endBounds.height()) + .apply() + val animator = ValueAnimator() + animator.setFloatValues(0f, 1f) + animator.setDuration(FADE_IN_ANIMATION_DURATION) + val t = SurfaceControl.Transaction() + animator.addListener(object : AnimatorListenerAdapter() { + override fun onAnimationStart(animation: Animator) { + t.show(leash) + t.apply() + } + + override fun onAnimationEnd(animation: Animator) { + finishCallback.onTransitionFinished(null) + } + }) + animator.addUpdateListener { animation: ValueAnimator -> + t.setAlpha(leash, animation.animatedFraction) + t.apply() + } + animator.start() + pendingTransitionTokens.remove(transition) + return true + } + + private fun findRelevantChange(info: TransitionInfo): TransitionInfo.Change { + val matchingChanges = + info.changes.filter { c -> + isValidTaskChange(c) && c.mode == TRANSIT_OPEN + } + if (matchingChanges.size != 1) { + throw IllegalStateException( + "Expected 1 relevant change but found: ${matchingChanges.size}" + ) + } + return matchingChanges.first() + } + + private fun isValidTaskChange(change: TransitionInfo.Change): Boolean { + return change.taskInfo != null && change.taskInfo?.taskId != -1 + } + + override fun handleRequest( + transition: IBinder, + request: TransitionRequestInfo + ): WindowContainerTransaction? { + return null + } + + companion object { + const val FADE_IN_ANIMATION_DURATION = 300L + } +} diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java index 09f9139cb1d5..bfc0ee803591 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicator.java @@ -16,7 +16,6 @@ package com.android.wm.shell.desktopmode; -import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM; import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN; import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW; import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; @@ -29,7 +28,6 @@ import android.animation.ValueAnimator; import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityManager; -import android.app.WindowConfiguration; import android.content.Context; import android.content.res.Resources; import android.graphics.PixelFormat; @@ -70,6 +68,37 @@ public class DesktopModeVisualIndicator { TO_SPLIT_RIGHT_INDICATOR } + /** + * The conditions surrounding the drag event that led to the indicator's creation. + */ + public enum DragStartState { + /** The indicator is resulting from a freeform task drag. */ + FROM_FREEFORM, + /** The indicator is resulting from a split screen task drag */ + FROM_SPLIT, + /** The indicator is resulting from a fullscreen task drag */ + FROM_FULLSCREEN, + /** The indicator is resulting from an Intent generated during a drag-and-drop event */ + DRAGGED_INTENT; + + /** + * Get the {@link DragStartState} of a drag event based on the windowing mode of the task. + * Note that DRAGGED_INTENT will be specified by the caller if needed and not returned + * here. + */ + public static DesktopModeVisualIndicator.DragStartState getDragStartState( + ActivityManager.RunningTaskInfo taskInfo + ) { + if (taskInfo.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) { + return FROM_FULLSCREEN; + } else if (taskInfo.getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW) { + return FROM_SPLIT; + } else if (taskInfo.isFreeform()) { + return FROM_FREEFORM; + } else return null; + } + } + private final Context mContext; private final DisplayController mDisplayController; private final RootTaskDisplayAreaOrganizer mRootTdaOrganizer; @@ -82,11 +111,13 @@ public class DesktopModeVisualIndicator { private View mView; private IndicatorType mCurrentType; + private DragStartState mDragStartState; public DesktopModeVisualIndicator(SyncTransactionQueue syncQueue, ActivityManager.RunningTaskInfo taskInfo, DisplayController displayController, Context context, SurfaceControl taskSurface, - RootTaskDisplayAreaOrganizer taskDisplayAreaOrganizer) { + RootTaskDisplayAreaOrganizer taskDisplayAreaOrganizer, + DragStartState dragStartState) { mSyncQueue = syncQueue; mTaskInfo = taskInfo; mDisplayController = displayController; @@ -94,6 +125,7 @@ public class DesktopModeVisualIndicator { mTaskSurface = taskSurface; mRootTdaOrganizer = taskDisplayAreaOrganizer; mCurrentType = IndicatorType.NO_INDICATOR; + mDragStartState = dragStartState; } /** @@ -101,7 +133,7 @@ public class DesktopModeVisualIndicator { * display, including no visible indicator. */ @NonNull - IndicatorType updateIndicatorType(PointF inputCoordinates, int windowingMode) { + IndicatorType updateIndicatorType(PointF inputCoordinates) { final DisplayLayout layout = mDisplayController.getDisplayLayout(mTaskInfo.displayId); // If we are in freeform, we don't want a visible indicator in the "freeform" drag zone. IndicatorType result = IndicatorType.NO_INDICATOR; @@ -111,14 +143,13 @@ public class DesktopModeVisualIndicator { // account for the possibility of the task going off the top of the screen by captionHeight final int captionHeight = mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.desktop_mode_freeform_decor_caption_height); - final Region fullscreenRegion = calculateFullscreenRegion(layout, windowingMode, + final Region fullscreenRegion = calculateFullscreenRegion(layout, captionHeight); + final Region splitLeftRegion = calculateSplitLeftRegion(layout, transitionAreaWidth, captionHeight); - final Region splitLeftRegion = calculateSplitLeftRegion(layout, windowingMode, - transitionAreaWidth, captionHeight); - final Region splitRightRegion = calculateSplitRightRegion(layout, windowingMode, - transitionAreaWidth, captionHeight); - final Region toDesktopRegion = calculateToDesktopRegion(layout, windowingMode, - splitLeftRegion, splitRightRegion, fullscreenRegion); + final Region splitRightRegion = calculateSplitRightRegion(layout, transitionAreaWidth, + captionHeight); + final Region toDesktopRegion = calculateToDesktopRegion(layout, splitLeftRegion, + splitRightRegion, fullscreenRegion); if (fullscreenRegion.contains((int) inputCoordinates.x, (int) inputCoordinates.y)) { result = IndicatorType.TO_FULLSCREEN_INDICATOR; } @@ -131,20 +162,22 @@ public class DesktopModeVisualIndicator { if (toDesktopRegion.contains((int) inputCoordinates.x, (int) inputCoordinates.y)) { result = IndicatorType.TO_DESKTOP_INDICATOR; } - transitionIndicator(result); + if (mDragStartState != DragStartState.DRAGGED_INTENT) { + transitionIndicator(result); + } return result; } @VisibleForTesting - Region calculateFullscreenRegion(DisplayLayout layout, - @WindowConfiguration.WindowingMode int windowingMode, int captionHeight) { + Region calculateFullscreenRegion(DisplayLayout layout, int captionHeight) { final Region region = new Region(); - int transitionHeight = windowingMode == WINDOWING_MODE_FREEFORM + int transitionHeight = mDragStartState == DragStartState.FROM_FREEFORM + || mDragStartState == DragStartState.DRAGGED_INTENT ? mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.desktop_mode_transition_region_thickness) : 2 * layout.stableInsets().top; // A Rect at the top of the screen that takes up the center 40%. - if (windowingMode == WINDOWING_MODE_FREEFORM) { + if (mDragStartState == DragStartState.FROM_FREEFORM) { final float toFullscreenScale = mContext.getResources().getFloat( R.dimen.desktop_mode_fullscreen_region_scale); final float toFullscreenWidth = (layout.width() * toFullscreenScale); @@ -153,9 +186,11 @@ public class DesktopModeVisualIndicator { (int) ((layout.width() / 2f) + (toFullscreenWidth / 2f)), transitionHeight)); } - // A screen-wide Rect if the task is in fullscreen or split. - if (windowingMode == WINDOWING_MODE_FULLSCREEN - || windowingMode == WINDOWING_MODE_MULTI_WINDOW) { + // A screen-wide Rect if the task is in fullscreen, split, or a dragged intent. + if (mDragStartState == DragStartState.FROM_FULLSCREEN + || mDragStartState == DragStartState.FROM_SPLIT + || mDragStartState == DragStartState.DRAGGED_INTENT + ) { region.union(new Rect(0, -captionHeight, layout.width(), @@ -166,12 +201,11 @@ public class DesktopModeVisualIndicator { @VisibleForTesting Region calculateToDesktopRegion(DisplayLayout layout, - @WindowConfiguration.WindowingMode int windowingMode, Region splitLeftRegion, Region splitRightRegion, Region toFullscreenRegion) { final Region region = new Region(); // If in desktop, we need no region. Otherwise it's the same for all windowing modes. - if (windowingMode != WINDOWING_MODE_FREEFORM) { + if (mDragStartState != DragStartState.FROM_FREEFORM) { region.union(new Rect(0, 0, layout.width(), layout.height())); region.op(splitLeftRegion, Region.Op.DIFFERENCE); region.op(splitRightRegion, Region.Op.DIFFERENCE); @@ -182,11 +216,10 @@ public class DesktopModeVisualIndicator { @VisibleForTesting Region calculateSplitLeftRegion(DisplayLayout layout, - @WindowConfiguration.WindowingMode int windowingMode, int transitionEdgeWidth, int captionHeight) { final Region region = new Region(); // In freeform, keep the top corners clear. - int transitionHeight = windowingMode == WINDOWING_MODE_FREEFORM + int transitionHeight = mDragStartState == DragStartState.FROM_FREEFORM ? mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.desktop_mode_split_from_desktop_height) : -captionHeight; @@ -196,11 +229,10 @@ public class DesktopModeVisualIndicator { @VisibleForTesting Region calculateSplitRightRegion(DisplayLayout layout, - @WindowConfiguration.WindowingMode int windowingMode, int transitionEdgeWidth, int captionHeight) { final Region region = new Region(); // In freeform, keep the top corners clear. - int transitionHeight = windowingMode == WINDOWING_MODE_FREEFORM + int transitionHeight = mDragStartState == DragStartState.FROM_FREEFORM ? mContext.getResources().getDimensionPixelSize( com.android.wm.shell.R.dimen.desktop_mode_split_from_desktop_height) : -captionHeight; diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index 0cf0345f024d..f36e620ce10f 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -34,10 +34,12 @@ import android.graphics.Point import android.graphics.PointF import android.graphics.Rect import android.graphics.Region +import android.os.Binder import android.os.IBinder import android.os.SystemProperties import android.util.Size import android.view.Display.DEFAULT_DISPLAY +import android.view.DragEvent import android.view.SurfaceControl import android.view.WindowManager.TRANSIT_CHANGE import android.view.WindowManager.TRANSIT_NONE @@ -69,6 +71,7 @@ import com.android.wm.shell.common.SyncTransactionQueue import com.android.wm.shell.common.desktopmode.DesktopModeTransitionSource import com.android.wm.shell.compatui.isTopActivityExemptFromDesktopWindowing import com.android.wm.shell.desktopmode.DesktopModeTaskRepository.VisibleTasksListener +import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.DragStartState import com.android.wm.shell.desktopmode.DesktopModeVisualIndicator.IndicatorType import com.android.wm.shell.desktopmode.DragToDesktopTransitionHandler.DragToDesktopStateListener import com.android.wm.shell.draganddrop.DragAndDropController @@ -121,6 +124,7 @@ class DesktopTasksController( private val returnToDragStartAnimator: ReturnToDragStartAnimator, private val enterDesktopTaskTransitionHandler: EnterDesktopTaskTransitionHandler, private val exitDesktopTaskTransitionHandler: ExitDesktopTaskTransitionHandler, + private val desktopModeDragAndDropTransitionHandler: DesktopModeDragAndDropTransitionHandler, private val toggleResizeDesktopTaskTransitionHandler: ToggleResizeDesktopTaskTransitionHandler, private val dragToDesktopTransitionHandler: DragToDesktopTransitionHandler, private val taskRepository: DesktopModeTaskRepository, @@ -176,6 +180,9 @@ class DesktopTasksController( private var recentsAnimationRunning = false private lateinit var splitScreenController: SplitScreenController + // Launch cookie used to identify a drag and drop transition to fullscreen after it has begun. + // Used to prevent handleRequest from moving the new fullscreen task to freeform. + private var dragAndDropFullscreenCookie: Binder? = null init { desktopMode = DesktopModeImpl() @@ -858,6 +865,7 @@ class DesktopTasksController( val triggerTask = request.triggerTask var shouldHandleMidRecentsFreeformLaunch = recentsAnimationRunning && isFreeformRelaunch(triggerTask, request) + val isDragAndDropFullscreenTransition = taskContainsDragAndDropCookie(triggerTask) val shouldHandleRequest = when { // Handle freeform relaunch during recents animation @@ -866,6 +874,13 @@ class DesktopTasksController( reason = "recents animation is running" false } + // Don't handle request if this was a tear to fullscreen transition. + // handleFullscreenTaskLaunch moves fullscreen intents to freeform; + // this is an exception to the rule + isDragAndDropFullscreenTransition -> { + dragAndDropFullscreenCookie = null + false + } // Handle task closing for the last window if wallpaper is available shouldHandleTaskClosing(request) -> true // Only handle open or to front transitions @@ -884,8 +899,7 @@ class DesktopTasksController( false } // Only handle fullscreen or freeform tasks - triggerTask.windowingMode != WINDOWING_MODE_FULLSCREEN && - triggerTask.windowingMode != WINDOWING_MODE_FREEFORM -> { + !triggerTask.isFullscreen && !triggerTask.isFreeform -> { reason = "windowingMode not handled (${triggerTask.windowingMode})" false } @@ -920,6 +934,9 @@ class DesktopTasksController( return result } + private fun taskContainsDragAndDropCookie(taskInfo: RunningTaskInfo?) = + taskInfo?.launchCookies?.any { it == dragAndDropFullscreenCookie } ?: false + /** * Applies the proper surface states (rounded corners) to tasks when desktop mode is active. * This is intended to be used when desktop mode is part of another animation but isn't, itself, @@ -1319,15 +1336,17 @@ class DesktopTasksController( taskBounds: Rect ) { if (taskInfo.windowingMode != WINDOWING_MODE_FREEFORM) return - updateVisualIndicator(taskInfo, taskSurface, inputX, taskBounds.top.toFloat()) + updateVisualIndicator(taskInfo, taskSurface, inputX, taskBounds.top.toFloat(), + DragStartState.FROM_FREEFORM) } fun updateVisualIndicator( taskInfo: RunningTaskInfo, - taskSurface: SurfaceControl, + taskSurface: SurfaceControl?, inputX: Float, - taskTop: Float - ): IndicatorType { + taskTop: Float, + dragStartState: DragStartState + ): DesktopModeVisualIndicator.IndicatorType { // If the visual indicator does not exist, create it. val indicator = visualIndicator @@ -1337,10 +1356,11 @@ class DesktopTasksController( displayController, context, taskSurface, - rootTaskDisplayAreaOrganizer + rootTaskDisplayAreaOrganizer, + dragStartState ) if (visualIndicator == null) visualIndicator = indicator - return indicator.updateIndicatorType(PointF(inputX, taskTop), taskInfo.windowingMode) + return indicator.updateIndicatorType(PointF(inputX, taskTop)) } /** @@ -1373,7 +1393,6 @@ class DesktopTasksController( val indicatorType = indicator.updateIndicatorType( PointF(inputCoordinate.x, currentDragBounds.top.toFloat()), - taskInfo.windowingMode ) when (indicatorType) { IndicatorType.TO_FULLSCREEN_INDICATOR -> { @@ -1434,7 +1453,7 @@ class DesktopTasksController( // End the drag_hold CUJ interaction. interactionJankMonitor.end(CUJ_DESKTOP_MODE_ENTER_APP_HANDLE_DRAG_HOLD) val indicator = getVisualIndicator() ?: return IndicatorType.NO_INDICATOR - val indicatorType = indicator.updateIndicatorType(inputCoordinates, taskInfo.windowingMode) + val indicatorType = indicator.updateIndicatorType(inputCoordinates) when (indicatorType) { IndicatorType.TO_DESKTOP_INDICATOR -> { // Start a new jank interaction for the drag release to desktop window animation. @@ -1486,9 +1505,10 @@ class DesktopTasksController( taskRepository.setExclusionRegionListener(listener, callbackExecutor) } + // TODO(b/358114479): Move this implementation into a separate class. override fun onUnhandledDrag( launchIntent: PendingIntent, - dragSurface: SurfaceControl, + dragEvent: DragEvent, onFinishCallback: Consumer<Boolean> ): Boolean { // TODO(b/320797628): Pass through which display we are dropping onto @@ -1496,7 +1516,6 @@ class DesktopTasksController( // Not currently in desktop mode, ignore the drop return false } - val launchComponent = getComponent(launchIntent) if (!multiInstanceHelper.supportsMultiInstanceSplit(launchComponent)) { // TODO(b/320797628): Should only return early if there is an existing running task, and @@ -1504,20 +1523,69 @@ class DesktopTasksController( logV("Dropped intent does not support multi-instance") return false } - + val taskInfo = getFocusedFreeformTask(DEFAULT_DISPLAY) ?: return false + // TODO(b/358114479): Update drag and drop handling to give us visibility into when another + // window will accept a drag event. This way, we can hide the indicator when we won't + // be handling the transition here, allowing us to display the indicator accurately. + // For now, we create the indicator only on drag end and immediately dispose it. + val indicatorType = updateVisualIndicator(taskInfo, dragEvent.dragSurface, + dragEvent.x, dragEvent.y, + DragStartState.DRAGGED_INTENT) + releaseVisualIndicator() + val windowingMode = when (indicatorType) { + IndicatorType.TO_FULLSCREEN_INDICATOR -> { + WINDOWING_MODE_FULLSCREEN + } + IndicatorType.TO_SPLIT_LEFT_INDICATOR, + IndicatorType.TO_SPLIT_RIGHT_INDICATOR, + IndicatorType.TO_DESKTOP_INDICATOR + -> { + WINDOWING_MODE_FREEFORM + } + else -> error("Invalid indicator type: $indicatorType") + } + val displayLayout = displayController.getDisplayLayout(DEFAULT_DISPLAY) ?: return false + val newWindowBounds = Rect() + when (indicatorType) { + IndicatorType.TO_DESKTOP_INDICATOR -> { + // Use default bounds, but with the top-center at the drop point. + newWindowBounds.set(getDefaultDesktopTaskBounds(displayLayout)) + newWindowBounds.offsetTo( + dragEvent.x.toInt() - (newWindowBounds.width() / 2), + dragEvent.y.toInt() + ) + } + IndicatorType.TO_SPLIT_RIGHT_INDICATOR -> { + newWindowBounds.set(getSnapBounds(taskInfo, SnapPosition.RIGHT)) + } + IndicatorType.TO_SPLIT_LEFT_INDICATOR -> { + newWindowBounds.set(getSnapBounds(taskInfo, SnapPosition.LEFT)) + } + else -> { + // Use empty bounds for the fullscreen case. + } + } // Start a new transition to launch the app val opts = ActivityOptions.makeBasic().apply { - launchWindowingMode = WINDOWING_MODE_FREEFORM + launchWindowingMode = windowingMode + launchBounds = newWindowBounds + pendingIntentBackgroundActivityStartMode = + ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_ALLOW_ALWAYS pendingIntentLaunchFlags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_MULTIPLE_TASK - setPendingIntentBackgroundActivityStartMode( - ActivityOptions.MODE_BACKGROUND_ACTIVITY_START_DENIED - ) } + if (windowingMode == WINDOWING_MODE_FULLSCREEN) { + dragAndDropFullscreenCookie = Binder() + opts.launchCookie = dragAndDropFullscreenCookie + } val wct = WindowContainerTransaction() wct.sendPendingIntent(launchIntent, null, opts.toBundle()) - transitions.startTransition(TRANSIT_OPEN, wct, null /* handler */) + if (windowingMode == WINDOWING_MODE_FREEFORM) { + desktopModeDragAndDropTransitionHandler.handleDropEvent(wct) + } else { + transitions.startTransition(TRANSIT_OPEN, wct, null) + } // Report that this is handled by the listener onFinishCallback.accept(true) @@ -1525,7 +1593,7 @@ class DesktopTasksController( // We've assumed responsibility of cleaning up the drag surface, so do that now // TODO(b/320797628): Do an actual animation here for the drag surface val t = SurfaceControl.Transaction() - t.remove(dragSurface) + t.remove(dragEvent.dragSurface) t.apply() return true } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java index 6cc10ea92bb4..cf02fb5fde8e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DragAndDropController.java @@ -70,6 +70,7 @@ import com.android.wm.shell.common.RemoteCallable; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.protolog.ShellProtoLogGroup; import com.android.wm.shell.shared.annotations.ExternalMainThread; +import com.android.wm.shell.shared.desktopmode.DesktopModeStatus; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.sysui.ShellCommandHandler; import com.android.wm.shell.sysui.ShellController; @@ -127,7 +128,7 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll * drag. */ default boolean onUnhandledDrag(@NonNull PendingIntent launchIntent, - @NonNull SurfaceControl dragSurface, + @NonNull DragEvent dragEvent, @NonNull Consumer<Boolean> onFinishCallback) { return false; } @@ -329,9 +330,18 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll return false; } + DragSession dragSession = null; if (event.getAction() == ACTION_DRAG_STARTED) { mActiveDragDisplay = displayId; - pd.isHandlingDrag = DragUtils.canHandleDrag(event); + dragSession = new DragSession(ActivityTaskManager.getInstance(), + mDisplayController.getDisplayLayout(displayId), event.getClipData(), + event.getDragFlags()); + dragSession.initialize(); + final ActivityManager.RunningTaskInfo taskInfo = dragSession.runningTaskInfo; + // Desktop tasks will have their own drag handling. + final boolean isDesktopDrag = taskInfo != null && taskInfo.isFreeform() + && DesktopModeStatus.canEnterDesktopMode(mContext); + pd.isHandlingDrag = DragUtils.canHandleDrag(event) && !isDesktopDrag; ProtoLog.v(ShellProtoLogGroup.WM_SHELL_DRAG_AND_DROP, "Clip description: handlingDrag=%b itemCount=%d mimeTypes=%s flags=%s", pd.isHandlingDrag, event.getClipData().getItemCount(), @@ -349,10 +359,7 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll Slog.w(TAG, "Unexpected drag start during an active drag"); return false; } - pd.dragSession = new DragSession(ActivityTaskManager.getInstance(), - mDisplayController.getDisplayLayout(displayId), event.getClipData(), - event.getDragFlags()); - pd.dragSession.initialize(); + pd.dragSession = dragSession; pd.activeDragCount++; pd.dragLayout.prepare(pd.dragSession, mLogger.logStart(pd.dragSession)); if (pd.dragSession.hideDragSourceTaskId != -1) { @@ -437,7 +444,7 @@ public class DragAndDropController implements RemoteCallable<DragAndDropControll } final boolean handled = notifyListeners( - l -> l.onUnhandledDrag(launchIntent, dragEvent.getDragSurface(), onFinishCallback)); + l -> l.onUnhandledDrag(launchIntent, dragEvent, onFinishCallback)); if (!handled) { // Nobody handled this, we still have to notify WM onFinishCallback.accept(false); 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 12b47cf5e7d6..457b5112076e 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 @@ -1031,7 +1031,7 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { } final boolean shouldStartTransitionDrag = relevantDecor.checkTouchEventInFocusedCaptionHandle(ev) - || Flags.enableAdditionalWindowsAboveStatusBar(); + || Flags.enableAdditionalWindowsAboveStatusBar(); if (dragFromStatusBarAllowed && shouldStartTransitionDrag) { mTransitionDragActive = true; } @@ -1039,8 +1039,13 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { } case MotionEvent.ACTION_UP: { if (mTransitionDragActive) { + final DesktopModeVisualIndicator.DragStartState dragStartState = + DesktopModeVisualIndicator.DragStartState + .getDragStartState(relevantDecor.mTaskInfo); + if (dragStartState == null) return; mDesktopTasksController.updateVisualIndicator(relevantDecor.mTaskInfo, - relevantDecor.mTaskSurface, ev.getRawX(), ev.getRawY()); + relevantDecor.mTaskSurface, ev.getRawX(), ev.getRawY(), + dragStartState); mTransitionDragActive = false; if (mMoveToDesktopAnimator != null) { // Though this isn't a hover event, we need to update handle's hover state @@ -1080,10 +1085,15 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { && mMoveToDesktopAnimator == null) { return; } + final DesktopModeVisualIndicator.DragStartState dragStartState = + DesktopModeVisualIndicator.DragStartState + .getDragStartState(relevantDecor.mTaskInfo); + if (dragStartState == null) return; final DesktopModeVisualIndicator.IndicatorType indicatorType = mDesktopTasksController.updateVisualIndicator( relevantDecor.mTaskInfo, - relevantDecor.mTaskSurface, ev.getRawX(), ev.getRawY()); + relevantDecor.mTaskSurface, ev.getRawX(), ev.getRawY(), + dragStartState); if (indicatorType != TO_FULLSCREEN_INDICATOR) { if (mMoveToDesktopAnimator == null) { mMoveToDesktopAnimator = new MoveToDesktopAnimator( diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt index 2dea43b508ae..f558e87c4ed7 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopModeVisualIndicatorTest.kt @@ -17,9 +17,6 @@ package com.android.wm.shell.desktopmode import android.app.ActivityManager.RunningTaskInfo -import android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM -import android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN -import android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW import android.graphics.Rect import android.graphics.Region import android.testing.AndroidTestingRunner @@ -38,6 +35,11 @@ import org.junit.runner.RunWith import org.mockito.Mock import org.mockito.kotlin.whenever +/** + * Test class for [DesktopModeVisualIndicator] + * + * Usage: atest WMShellUnitTests:DesktopModeVisualIndicatorTest + */ @SmallTest @RunWith(AndroidTestingRunner::class) class DesktopModeVisualIndicatorTest : ShellTestCase() { @@ -52,8 +54,6 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() { @Before fun setUp() { - visualIndicator = DesktopModeVisualIndicator(syncQueue, taskInfo, displayController, - context, taskSurface, taskDisplayAreaOrganizer) whenever(displayLayout.width()).thenReturn(DISPLAY_BOUNDS.width()) whenever(displayLayout.height()).thenReturn(DISPLAY_BOUNDS.height()) whenever(displayLayout.stableInsets()).thenReturn(STABLE_INSETS) @@ -61,41 +61,52 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() { @Test fun testFullscreenRegionCalculation() { - var testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, - WINDOWING_MODE_FULLSCREEN, CAPTION_HEIGHT) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN) + var testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 2400, 2 * STABLE_INSETS.top)) - testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, - WINDOWING_MODE_FREEFORM, CAPTION_HEIGHT) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FREEFORM) + testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT) val transitionHeight = context.resources.getDimensionPixelSize( R.dimen.desktop_mode_transition_region_thickness) val toFullscreenScale = mContext.resources.getFloat( R.dimen.desktop_mode_fullscreen_region_scale ) val toFullscreenWidth = displayLayout.width() * toFullscreenScale - assertThat(testRegion.bounds).isEqualTo(Rect( (DISPLAY_BOUNDS.width() / 2f - toFullscreenWidth / 2f).toInt(), -50, (DISPLAY_BOUNDS.width() / 2f + toFullscreenWidth / 2f).toInt(), transitionHeight)) - testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, - WINDOWING_MODE_MULTI_WINDOW, CAPTION_HEIGHT) + + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_SPLIT) + testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 2400, 2 * STABLE_INSETS.top)) + + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.DRAGGED_INTENT) + testRegion = visualIndicator.calculateFullscreenRegion(displayLayout, CAPTION_HEIGHT) + assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 2400, transitionHeight)) } @Test fun testSplitLeftRegionCalculation() { val transitionHeight = context.resources.getDimensionPixelSize( R.dimen.desktop_mode_split_from_desktop_height) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN) var testRegion = visualIndicator.calculateSplitLeftRegion(displayLayout, - WINDOWING_MODE_FULLSCREEN, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 32, 1600)) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FREEFORM) testRegion = visualIndicator.calculateSplitLeftRegion(displayLayout, - WINDOWING_MODE_FREEFORM, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(0, transitionHeight, 32, 1600)) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_SPLIT) testRegion = visualIndicator.calculateSplitLeftRegion(displayLayout, - WINDOWING_MODE_MULTI_WINDOW, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 32, 1600)) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.DRAGGED_INTENT) + testRegion = visualIndicator.calculateSplitLeftRegion(displayLayout, + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(0, -50, 32, 1600)) } @@ -103,27 +114,35 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() { fun testSplitRightRegionCalculation() { val transitionHeight = context.resources.getDimensionPixelSize( R.dimen.desktop_mode_split_from_desktop_height) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN) var testRegion = visualIndicator.calculateSplitRightRegion(displayLayout, - WINDOWING_MODE_FULLSCREEN, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(2368, -50, 2400, 1600)) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FREEFORM) testRegion = visualIndicator.calculateSplitRightRegion(displayLayout, - WINDOWING_MODE_FREEFORM, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(2368, transitionHeight, 2400, 1600)) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_SPLIT) + testRegion = visualIndicator.calculateSplitRightRegion(displayLayout, + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + assertThat(testRegion.bounds).isEqualTo(Rect(2368, -50, 2400, 1600)) + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.DRAGGED_INTENT) testRegion = visualIndicator.calculateSplitRightRegion(displayLayout, - WINDOWING_MODE_MULTI_WINDOW, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) assertThat(testRegion.bounds).isEqualTo(Rect(2368, -50, 2400, 1600)) } @Test fun testToDesktopRegionCalculation() { + createVisualIndicator(DesktopModeVisualIndicator.DragStartState.FROM_FULLSCREEN) val fullscreenRegion = visualIndicator.calculateFullscreenRegion(displayLayout, - WINDOWING_MODE_FULLSCREEN, CAPTION_HEIGHT) + CAPTION_HEIGHT) val splitLeftRegion = visualIndicator.calculateSplitLeftRegion(displayLayout, - WINDOWING_MODE_FULLSCREEN, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) val splitRightRegion = visualIndicator.calculateSplitRightRegion(displayLayout, - WINDOWING_MODE_FULLSCREEN, TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) + TRANSITION_AREA_WIDTH, CAPTION_HEIGHT) val desktopRegion = visualIndicator.calculateToDesktopRegion(displayLayout, - WINDOWING_MODE_FULLSCREEN, splitLeftRegion, splitRightRegion, fullscreenRegion) + splitLeftRegion, splitRightRegion, fullscreenRegion) var testRegion = Region() testRegion.union(DISPLAY_BOUNDS) testRegion.op(splitLeftRegion, Region.Op.DIFFERENCE) @@ -132,6 +151,11 @@ class DesktopModeVisualIndicatorTest : ShellTestCase() { assertThat(desktopRegion).isEqualTo(testRegion) } + private fun createVisualIndicator(dragStartState: DesktopModeVisualIndicator.DragStartState) { + visualIndicator = DesktopModeVisualIndicator(syncQueue, taskInfo, displayController, + context, taskSurface, taskDisplayAreaOrganizer, dragStartState) + } + companion object { private const val TRANSITION_AREA_WIDTH = 32 private const val CAPTION_HEIGHT = 50 diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt index 616f3104eb88..ff52480ec9c5 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/desktopmode/DesktopTasksControllerTest.kt @@ -160,6 +160,7 @@ class DesktopTasksControllerTest : ShellTestCase() { @Mock lateinit var mReturnToDragStartAnimator: ReturnToDragStartAnimator @Mock lateinit var exitDesktopTransitionHandler: ExitDesktopTaskTransitionHandler @Mock lateinit var enterDesktopTransitionHandler: EnterDesktopTaskTransitionHandler + @Mock lateinit var dragAndDropTransitionHandler: DesktopModeDragAndDropTransitionHandler @Mock lateinit var toggleResizeDesktopTaskTransitionHandler: ToggleResizeDesktopTaskTransitionHandler @Mock lateinit var dragToDesktopTransitionHandler: DragToDesktopTransitionHandler @@ -254,6 +255,7 @@ class DesktopTasksControllerTest : ShellTestCase() { mReturnToDragStartAnimator, enterDesktopTransitionHandler, exitDesktopTransitionHandler, + dragAndDropTransitionHandler, toggleResizeDesktopTaskTransitionHandler, dragToDesktopTransitionHandler, taskRepository, @@ -2387,7 +2389,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_landscapeDevice_resizable_undefinedOrientation_defaultLandscapeBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = setUpFullscreenTask() @@ -2403,7 +2405,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_landscapeDevice_resizable_landscapeOrientation_defaultLandscapeBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = setUpFullscreenTask(screenOrientation = SCREEN_ORIENTATION_LANDSCAPE) @@ -2419,7 +2421,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_landscapeDevice_resizable_portraitOrientation_resizablePortraitBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = @@ -2436,7 +2438,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_landscapeDevice_unResizable_landscapeOrientation_defaultLandscapeBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = @@ -2453,7 +2455,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_landscapeDevice_unResizable_portraitOrientation_unResizablePortraitBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = @@ -2473,7 +2475,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_portraitDevice_resizable_undefinedOrientation_defaultPortraitBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = setUpFullscreenTask(deviceOrientation = ORIENTATION_PORTRAIT) @@ -2489,7 +2491,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_portraitDevice_resizable_portraitOrientation_defaultPortraitBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = @@ -2508,7 +2510,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_portraitDevice_resizable_landscapeOrientation_resizableLandscapeBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = @@ -2528,7 +2530,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_portraitDevice_unResizable_portraitOrientation_defaultPortraitBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = @@ -2548,7 +2550,7 @@ class DesktopTasksControllerTest : ShellTestCase() { fun dragToDesktop_portraitDevice_unResizable_landscapeOrientation_unResizableLandscapeBounds() { val spyController = spy(controller) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.TO_DESKTOP_INDICATOR) val task = @@ -2605,7 +2607,7 @@ class DesktopTasksControllerTest : ShellTestCase() { val currentDragBounds = Rect(100, 200, 500, 1000) whenever(spyController.getVisualIndicator()).thenReturn(desktopModeVisualIndicator) - whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull(), anyOrNull())) + whenever(desktopModeVisualIndicator.updateIndicatorType(anyOrNull())) .thenReturn(DesktopModeVisualIndicator.IndicatorType.NO_INDICATOR) spyController.onDragPositioningEnd( |