From 72f9136b29d976a95275c02d568db5a35b58553a Mon Sep 17 00:00:00 2001 From: mattsziklay Date: Wed, 5 Jul 2023 09:14:33 -0700 Subject: Enable split screen button in handle menu. Allows apps to begin split select from caption handle menu. This is compatible with both apps in fullscreen and freeform. Still to implement/known issues: - Different flow for desktop to split select when > 1 app is open on desktop. - Transition currently breaks when app chosen in split select is also open in desktop. Video: http://recall/-/gjymLwjdDT07aWqaK6101a/gU56zTDcWov6ukbKuH8tFx Bug: 286550932 Bug: 279586624 Test: Manual Change-Id: I32cbc44e4cd115e08a351943b1f39dbc116c55c1 --- .../com/android/wm/shell/dagger/WMShellModule.java | 3 +- .../shell/desktopmode/DesktopModeController.java | 5 ++ .../wm/shell/desktopmode/DesktopTasksController.kt | 60 ++++++++++++++++++++-- .../android/wm/shell/desktopmode/IDesktopMode.aidl | 4 ++ .../android/wm/shell/splitscreen/ISplitScreen.aidl | 13 ++++- .../wm/shell/splitscreen/ISplitSelectListener.aidl | 29 +++++++++++ .../android/wm/shell/splitscreen/SplitScreen.java | 8 +++ .../shell/splitscreen/SplitScreenController.java | 56 ++++++++++++++++++++ .../wm/shell/splitscreen/StageCoordinator.java | 20 ++++++++ .../splitscreen/tv/TvSplitScreenController.java | 2 +- .../DesktopModeWindowDecorViewModel.java | 5 ++ .../splitscreen/SplitScreenControllerTests.java | 4 +- 12 files changed, 202 insertions(+), 7 deletions(-) create mode 100644 libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitSelectListener.aidl (limited to 'libs/WindowManager/Shell') 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 881c8f5552b6..065e7b09a05d 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 @@ -325,12 +325,13 @@ public abstract class WMShellModule { Optional recentTasks, LaunchAdjacentController launchAdjacentController, Optional windowDecorViewModel, + Optional desktopTasksController, @ShellMainThread ShellExecutor mainExecutor) { return new SplitScreenController(context, shellInit, shellCommandHandler, shellController, shellTaskOrganizer, syncQueue, rootTaskDisplayAreaOrganizer, displayController, displayImeController, displayInsetsController, dragAndDropController, transitions, transactionPool, iconProvider, recentTasks, launchAdjacentController, - windowDecorViewModel, mainExecutor); + windowDecorViewModel, desktopTasksController, mainExecutor); } // diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java index db6c258e84c2..5b24d7a60c4e 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeController.java @@ -534,6 +534,11 @@ public class DesktopModeController implements RemoteCallable moveToFullscreen(task) } @@ -688,11 +705,41 @@ class DesktopTasksController( wct.setWindowingMode(taskInfo.token, targetWindowingMode) wct.setBounds(taskInfo.token, null) if (isDesktopDensityOverrideSet()) { - wct.setDensityDpi(taskInfo.token, getFullscreenDensityDpi()) + wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) } } - private fun getFullscreenDensityDpi(): Int { + /** + * Adds split screen changes to a transaction. Note that bounds are not reset here due to + * animation; see {@link onDesktopSplitSelectAnimComplete} + */ + private fun addMoveToSplitChanges( + wct: WindowContainerTransaction, + taskInfo: RunningTaskInfo + ) { + wct.setWindowingMode(taskInfo.token, WINDOWING_MODE_MULTI_WINDOW) + // The task's density may have been overridden in freeform; revert it here as we don't + // want it overridden in multi-window. + wct.setDensityDpi(taskInfo.token, getDefaultDensityDpi()) + } + + /** + * Requests a task be transitioned from desktop to split select. Applies needed windowing + * changes if this transition is enabled. + */ + fun requestSplit( + taskInfo: RunningTaskInfo + ) { + val windowingMode = taskInfo.windowingMode + if (windowingMode == WINDOWING_MODE_FULLSCREEN || windowingMode == WINDOWING_MODE_FREEFORM + ) { + val wct = WindowContainerTransaction() + addMoveToSplitChanges(wct, taskInfo) + splitScreenController.requestEnterSplitSelect(taskInfo, wct) + } + } + + private fun getDefaultDensityDpi(): Int { return context.resources.displayMetrics.densityDpi } @@ -969,6 +1016,13 @@ class DesktopTasksController( return result[0] } + override fun onDesktopSplitSelectAnimComplete(taskInfo: RunningTaskInfo) { + ExecutorUtils.executeRemoteCallWithTaskPermission( + controller, + "onDesktopSplitSelectAnimComplete" + ) { c -> c.onDesktopSplitSelectAnimComplete(taskInfo) } + } + override fun setTaskListener(listener: IDesktopTaskListener?) { KtProtoLog.v( WM_SHELL_DESKTOP_MODE, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopMode.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopMode.aidl index ee3a080e7318..47edfd455f5a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopMode.aidl +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/IDesktopMode.aidl @@ -16,6 +16,7 @@ package com.android.wm.shell.desktopmode; +import android.app.ActivityManager.RunningTaskInfo; import com.android.wm.shell.desktopmode.IDesktopTaskListener; /** @@ -38,6 +39,9 @@ interface IDesktopMode { /** Get count of visible desktop tasks on the given display */ int getVisibleTaskCount(int displayId); + /** Perform cleanup transactions after the animation to split select is complete */ + oneway void onDesktopSplitSelectAnimComplete(in RunningTaskInfo taskInfo); + /** Set listener that will receive callbacks about updates to desktop tasks */ oneway void setTaskListener(IDesktopTaskListener listener); } \ No newline at end of file diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl index c414e708b28d..14304a3c0aac 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitScreen.aidl @@ -27,6 +27,7 @@ import android.view.RemoteAnimationTarget; import android.window.RemoteTransition; import com.android.wm.shell.splitscreen.ISplitScreenListener; +import com.android.wm.shell.splitscreen.ISplitSelectListener; /** * Interface that is exposed to remote callers to manipulate the splitscreen feature. @@ -43,6 +44,16 @@ interface ISplitScreen { */ oneway void unregisterSplitScreenListener(in ISplitScreenListener listener) = 2; + /** + * Registers a split select listener. + */ + oneway void registerSplitSelectListener(in ISplitSelectListener listener) = 20; + + /** + * Unregisters a split select listener. + */ + oneway void unregisterSplitSelectListener(in ISplitSelectListener listener) = 21; + /** * Removes a task from the side stage. */ @@ -148,4 +159,4 @@ interface ISplitScreen { */ RemoteAnimationTarget[] onStartingSplitLegacy(in RemoteAnimationTarget[] appTargets) = 14; } -// Last id = 19 \ No newline at end of file +// Last id = 21 \ No newline at end of file diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitSelectListener.aidl b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitSelectListener.aidl new file mode 100644 index 000000000000..7171da5d885d --- /dev/null +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/ISplitSelectListener.aidl @@ -0,0 +1,29 @@ +/* + * Copyright (C) 2021 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.splitscreen; + +import android.app.ActivityManager.RunningTaskInfo; + +/** + * Listener interface that Launcher attaches to SystemUI to get split-select callbacks. + */ +interface ISplitSelectListener { + /** + * Called when a task requests to enter split select + */ + boolean onRequestSplitSelect(in RunningTaskInfo taskInfo); +} \ No newline at end of file diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java index 2f2bc77b804b..f20fe0b88e12 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreen.java @@ -18,6 +18,7 @@ package com.android.wm.shell.splitscreen; import android.annotation.IntDef; import android.annotation.NonNull; +import android.app.ActivityManager; import android.graphics.Rect; import com.android.wm.shell.common.annotations.ExternalThread; @@ -63,6 +64,13 @@ public interface SplitScreen { default void onSplitVisibilityChanged(boolean visible) {} } + /** Callback interface for listening to requests to enter split select */ + interface SplitSelectListener { + default boolean onRequestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo) { + return false; + } + } + /** Registers listener that gets split screen callback. */ void registerSplitScreenListener(@NonNull SplitScreenListener listener, @NonNull Executor executor); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java index 7699b4bfd13a..b1d444fdc4a0 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java @@ -87,6 +87,7 @@ import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.common.annotations.ExternalThread; import com.android.wm.shell.common.split.SplitScreenConstants.SplitPosition; import com.android.wm.shell.common.split.SplitScreenUtils; +import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.draganddrop.DragAndDropPolicy; import com.android.wm.shell.protolog.ShellProtoLogGroup; @@ -104,6 +105,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Optional; import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicBoolean; /** * Class manages split-screen multitasking mode and implements the main interface @@ -177,6 +179,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, private final Optional mRecentTasksOptional; private final LaunchAdjacentController mLaunchAdjacentController; private final Optional mWindowDecorViewModel; + private final Optional mDesktopTasksController; private final SplitScreenShellCommandHandler mSplitScreenShellCommandHandler; private final String[] mAppsSupportMultiInstances; @@ -205,6 +208,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, Optional recentTasks, LaunchAdjacentController launchAdjacentController, Optional windowDecorViewModel, + Optional desktopTasksController, ShellExecutor mainExecutor) { mShellCommandHandler = shellCommandHandler; mShellController = shellController; @@ -223,6 +227,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mRecentTasksOptional = recentTasks; mLaunchAdjacentController = launchAdjacentController; mWindowDecorViewModel = windowDecorViewModel; + mDesktopTasksController = desktopTasksController; mSplitScreenShellCommandHandler = new SplitScreenShellCommandHandler(this); // TODO(b/238217847): Temporarily add this check here until we can remove the dynamic // override for this controller from the base module @@ -254,6 +259,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, RecentTasksController recentTasks, LaunchAdjacentController launchAdjacentController, WindowDecorViewModel windowDecorViewModel, + DesktopTasksController desktopTasksController, ShellExecutor mainExecutor, StageCoordinator stageCoordinator) { mShellCommandHandler = shellCommandHandler; @@ -273,6 +279,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mRecentTasksOptional = Optional.of(recentTasks); mLaunchAdjacentController = launchAdjacentController; mWindowDecorViewModel = Optional.of(windowDecorViewModel); + mDesktopTasksController = Optional.of(desktopTasksController); mStageCoordinator = stageCoordinator; mSplitScreenShellCommandHandler = new SplitScreenShellCommandHandler(this); shellInit.addInitCallback(this::onInit, this); @@ -306,6 +313,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } mDragAndDropController.ifPresent(controller -> controller.setSplitScreenController(this)); mWindowDecorViewModel.ifPresent(viewModel -> viewModel.setSplitScreenController(this)); + mDesktopTasksController.ifPresent(controller -> controller.setSplitScreenController(this)); } protected StageCoordinator createStageCoordinator() { @@ -467,6 +475,16 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, mStageCoordinator.unregisterSplitScreenListener(listener); } + /** Register a split select listener */ + public void registerSplitSelectListener(SplitScreen.SplitSelectListener listener) { + mStageCoordinator.registerSplitSelectListener(listener); + } + + /** Unregister a split select listener */ + public void unregisterSplitSelectListener(SplitScreen.SplitSelectListener listener) { + mStageCoordinator.unregisterSplitSelectListener(listener); + } + public void goToFullscreenFromSplit() { mStageCoordinator.goToFullscreenFromSplit(); } @@ -484,6 +502,16 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, return mStageCoordinator.getActivateSplitPosition(taskInfo); } + /** + * Move a task to split select + * @param taskInfo the task being moved to split select + * @param wct transaction to apply if this is a valid request + */ + public void requestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo, + WindowContainerTransaction wct) { + mStageCoordinator.requestEnterSplitSelect(taskInfo, wct); + } + public void startTask(int taskId, @SplitPosition int position, @Nullable Bundle options) { final int[] result = new int[1]; IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() { @@ -1087,6 +1115,8 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, private SplitScreenController mController; private final SingleInstanceRemoteListener mListener; + private final SingleInstanceRemoteListener mSelectListener; private final SplitScreen.SplitScreenListener mSplitScreenListener = new SplitScreen.SplitScreenListener() { @Override @@ -1100,11 +1130,25 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, } }; + private final SplitScreen.SplitSelectListener mSplitSelectListener = + new SplitScreen.SplitSelectListener() { + @Override + public boolean onRequestEnterSplitSelect( + ActivityManager.RunningTaskInfo taskInfo) { + AtomicBoolean result = new AtomicBoolean(false); + mSelectListener.call(l -> result.set(l.onRequestSplitSelect(taskInfo))); + return result.get(); + } + }; + public ISplitScreenImpl(SplitScreenController controller) { mController = controller; mListener = new SingleInstanceRemoteListener<>(controller, c -> c.registerSplitScreenListener(mSplitScreenListener), c -> c.unregisterSplitScreenListener(mSplitScreenListener)); + mSelectListener = new SingleInstanceRemoteListener<>(controller, + c -> c.registerSplitSelectListener(mSplitSelectListener), + c -> c.unregisterSplitSelectListener(mSplitSelectListener)); } /** @@ -1129,6 +1173,18 @@ public class SplitScreenController implements DragAndDropPolicy.Starter, (controller) -> mListener.unregister()); } + @Override + public void registerSplitSelectListener(ISplitSelectListener listener) { + executeRemoteCallWithTaskPermission(mController, "registerSplitSelectListener", + (controller) -> mSelectListener.register(listener)); + } + + @Override + public void unregisterSplitSelectListener(ISplitSelectListener listener) { + executeRemoteCallWithTaskPermission(mController, "unregisterSplitSelectListener", + (controller) -> mSelectListener.unregister()); + } + @Override public void exitSplitScreen(int toTopTaskId) { executeRemoteCallWithTaskPermission(mController, "exitSplitScreen", 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 7d62f58014f0..ac8ad8e461f4 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 @@ -145,8 +145,10 @@ import com.android.wm.shell.windowdecor.WindowDecorViewModel; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.Set; /** * Coordinates the staging (visibility, sizing, ...) of the split-screen {@link MainStage} and @@ -186,6 +188,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, private final ShellTaskOrganizer mTaskOrganizer; private final Context mContext; private final List mListeners = new ArrayList<>(); + private final Set mSelectListeners = new HashSet<>(); private final DisplayController mDisplayController; private final DisplayImeController mDisplayImeController; private final DisplayInsetsController mDisplayInsetsController; @@ -463,6 +466,15 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, return mLogger; } + void requestEnterSplitSelect(ActivityManager.RunningTaskInfo taskInfo, + WindowContainerTransaction wct) { + boolean enteredSplitSelect = false; + for (SplitScreen.SplitSelectListener listener : mSelectListeners) { + enteredSplitSelect |= listener.onRequestEnterSplitSelect(taskInfo); + } + if (enteredSplitSelect) mTaskOrganizer.applyTransaction(wct); + } + void startShortcut(String packageName, String shortcutId, @SplitPosition int position, Bundle options, UserHandle user) { final boolean isEnteringSplit = !isSplitActive(); @@ -1658,6 +1670,14 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler, mListeners.remove(listener); } + void registerSplitSelectListener(SplitScreen.SplitSelectListener listener) { + mSelectListeners.add(listener); + } + + void unregisterSplitSelectListener(SplitScreen.SplitSelectListener listener) { + mSelectListeners.remove(listener); + } + void sendStatusToListener(SplitScreen.SplitScreenListener listener) { listener.onStagePositionChanged(STAGE_TYPE_MAIN, getMainStagePosition()); listener.onStagePositionChanged(STAGE_TYPE_SIDE, getSideStagePosition()); diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java index a2301b133426..c10142588bde 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/tv/TvSplitScreenController.java @@ -87,7 +87,7 @@ public class TvSplitScreenController extends SplitScreenController { syncQueue, rootTDAOrganizer, displayController, displayImeController, displayInsetsController, dragAndDropController, transitions, transactionPool, iconProvider, recentTasks, launchAdjacentController, Optional.empty(), - mainExecutor); + Optional.empty(), mainExecutor); mTaskOrganizer = shellTaskOrganizer; mSyncQueue = syncQueue; 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 2b19da2498a6..2be7a491fdf2 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 @@ -365,6 +365,11 @@ public class DesktopModeWindowDecorViewModel implements WindowDecorViewModel { mDesktopModeController.ifPresent(c -> c.setDesktopModeActive(false)); mDesktopTasksController.ifPresent(c -> c.moveToFullscreen(mTaskId)); decoration.closeHandleMenu(); + } else if (id == R.id.split_screen_button) { + decoration.closeHandleMenu(); + mDesktopTasksController.ifPresent(c -> { + c.requestSplit(decoration.mTaskInfo); + }); } else if (id == R.id.collapse_menu_button) { decoration.closeHandleMenu(); } else if (id == R.id.select_button) { diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java index e8a1e91acd4d..568db919818c 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitScreenControllerTests.java @@ -65,6 +65,7 @@ import com.android.wm.shell.common.LaunchAdjacentController; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.TransactionPool; +import com.android.wm.shell.desktopmode.DesktopTasksController; import com.android.wm.shell.draganddrop.DragAndDropController; import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.sysui.ShellCommandHandler; @@ -106,6 +107,7 @@ public class SplitScreenControllerTests extends ShellTestCase { @Mock RecentTasksController mRecentTasks; @Mock LaunchAdjacentController mLaunchAdjacentController; @Mock WindowDecorViewModel mWindowDecorViewModel; + @Mock DesktopTasksController mDesktopTasksController; @Captor ArgumentCaptor mIntentCaptor; private ShellController mShellController; @@ -122,7 +124,7 @@ public class SplitScreenControllerTests extends ShellTestCase { mRootTDAOrganizer, mDisplayController, mDisplayImeController, mDisplayInsetsController, mDragAndDropController, mTransitions, mTransactionPool, mIconProvider, mRecentTasks, mLaunchAdjacentController, mWindowDecorViewModel, - mMainExecutor, mStageCoordinator)); + mDesktopTasksController, mMainExecutor, mStageCoordinator)); } @Test -- cgit v1.2.3-59-g8ed1b