From c97bb4600f350d6a9b3a8a89990e8349c8f5df1c Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Thu, 16 Feb 2023 17:43:32 -0800 Subject: [PATCH] Move split functions from RecentsView to SplitSelectStateController * Moving things out of RecentsView to avoid dependency on a non-testable class * Also helping prevent bloating RecentsView.java Bug: 266482558 Test: Single Chrome instance in recents. Initiate split with Chrome from workspace, tap on Chrome again in Taskbar, ensure no crash. Change-Id: I99ec704479ffaa860f4d80c2cb9f54182f31f41a --- .../taskbar/TaskbarActivityContext.java | 4 +- .../taskbar/TaskbarUIController.java | 8 +-- .../uioverrides/QuickstepLauncher.java | 27 +++++----- .../util/SplitSelectStateController.java | 51 ++++++++++++++++++- .../android/quickstep/views/RecentsView.java | 47 ----------------- 5 files changed, 68 insertions(+), 69 deletions(-) diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java index c6d8fce99b..a1bcf16627 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java @@ -870,9 +870,9 @@ public class TaskbarActivityContext extends BaseTaskbarContext { * (potentially breaking a split pair). */ private void launchFromTaskbarPreservingSplitIfVisible(RecentsView recents, ItemInfo info) { - recents.findLastActiveTaskAndRunCallback( + recents.getSplitSelectController().findLastActiveTaskAndRunCallback( info.getTargetComponent(), - (Consumer) foundTask -> { + foundTask -> { if (foundTask != null) { TaskView foundTaskView = recents.getTaskViewByTaskId(foundTask.key.id); diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java index bfdf156dbd..ae7fff3f11 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java @@ -174,9 +174,9 @@ public class TaskbarUIController { if (recentsView == null) { return; } - recentsView.findLastActiveTaskAndRunCallback( + recentsView.getSplitSelectController().findLastActiveTaskAndRunCallback( splitSelectSource.intent.getComponent(), - (Consumer) foundTask -> { + foundTask -> { splitSelectSource.alreadyRunningTaskId = foundTask == null ? INVALID_TASK_ID : foundTask.key.id; @@ -191,9 +191,9 @@ public class TaskbarUIController { */ public void triggerSecondAppForSplit(ItemInfoWithIcon info, Intent intent, View startingView) { RecentsView recents = getRecentsView(); - recents.findLastActiveTaskAndRunCallback( + recents.getSplitSelectController().findLastActiveTaskAndRunCallback( info.getTargetComponent(), - (Consumer) foundTask -> { + foundTask -> { if (foundTask != null) { TaskView foundTaskView = recents.getTaskViewByTaskId(foundTask.key.id); // TODO (b/266482558): This additional null check is needed because there diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java index fd986e6188..b2745f26cc 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java +++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java @@ -576,9 +576,9 @@ public class QuickstepLauncher extends Launcher { RecentsView recentsView = getOverviewPanel(); // Check if there is already an instance of this app running, if so, initiate the split // using that. - recentsView.findLastActiveTaskAndRunCallback( + mSplitSelectStateController.findLastActiveTaskAndRunCallback( splitSelectSource.intent.getComponent(), - (Consumer) foundTask -> { + foundTask -> { splitSelectSource.alreadyRunningTaskId = foundTask == null ? INVALID_TASK_ID : foundTask.key.id; @@ -592,8 +592,7 @@ public class QuickstepLauncher extends Launcher { } /** TODO(b/266482558) Migrate into SplitSelectStateController or someplace split specific. */ - private void startSplitToHome( - SplitSelectSource source) { + private void startSplitToHome(SplitSelectSource source) { AbstractFloatingView.closeAllOpenViews(this); int splitPlaceholderSize = getResources().getDimensionPixelSize( R.dimen.split_placeholder_size); @@ -601,14 +600,14 @@ public class QuickstepLauncher extends Launcher { R.dimen.split_placeholder_inset); Rect tempRect = new Rect(); - SplitSelectStateController controller = getSplitSelectStateController(); - controller.setInitialTaskSelect(source.intent, source.position.stagePosition, - source.itemInfo, source.splitEvent, source.alreadyRunningTaskId); + mSplitSelectStateController.setInitialTaskSelect(source.intent, + source.position.stagePosition, source.itemInfo, source.splitEvent, + source.alreadyRunningTaskId); RecentsView recentsView = getOverviewPanel(); recentsView.getPagedOrientationHandler().getInitialSplitPlaceholderBounds( splitPlaceholderSize, splitPlaceholderInset, getDeviceProfile(), - controller.getActiveSplitStagePosition(), tempRect); + mSplitSelectStateController.getActiveSplitStagePosition(), tempRect); PendingAnimation anim = new PendingAnimation(TABLET_HOME_TO_SPLIT.getDuration()); RectF startingTaskRect = new RectF(); @@ -617,12 +616,12 @@ public class QuickstepLauncher extends Launcher { floatingTaskView.setAlpha(1); floatingTaskView.addStagingAnimation(anim, startingTaskRect, tempRect, false /* fadeWithThumbnail */, true /* isStagedTask */); - controller.setFirstFloatingTaskView(floatingTaskView); + mSplitSelectStateController.setFirstFloatingTaskView(floatingTaskView); anim.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationCancel(Animator animation) { getDragLayer().removeView(floatingTaskView); - controller.resetState(); + mSplitSelectStateController.resetState(); } }); anim.buildAnim().start(); @@ -1153,14 +1152,12 @@ public class QuickstepLauncher extends Launcher { // Launcher to first restore into Overview state, wait for the relevant tasks and icons to // load in, and then proceed to OverviewSplitSelect. if (isInState(OVERVIEW_SPLIT_SELECT)) { - SplitSelectStateController splitSelectStateController = - ((RecentsView) getOverviewPanel()).getSplitSelectController(); // Launcher will restart in Overview and then transition to OverviewSplitSelect. outState.putIBinder(PENDING_SPLIT_SELECT_INFO, ObjectWrapper.wrap( new PendingSplitSelectInfo( - splitSelectStateController.getInitialTaskId(), - splitSelectStateController.getActiveSplitStagePosition(), - splitSelectStateController.getSplitEvent()) + mSplitSelectStateController.getInitialTaskId(), + mSplitSelectStateController.getActiveSplitStagePosition(), + mSplitSelectStateController.getSplitEvent()) )); outState.putInt(RUNTIME_STATE, OVERVIEW.ordinal); } diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java index 1b2bfc94fc..51afb5b1d2 100644 --- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java @@ -29,6 +29,7 @@ import android.app.ActivityManager; import android.app.ActivityOptions; import android.app.ActivityThread; import android.app.PendingIntent; +import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; @@ -59,6 +60,7 @@ import com.android.launcher3.testing.TestLogging; import com.android.launcher3.testing.shared.TestProtocol; import com.android.launcher3.util.SplitConfigurationOptions; import com.android.launcher3.util.SplitConfigurationOptions.StagePosition; +import com.android.quickstep.RecentsModel; import com.android.quickstep.SystemUiProxy; import com.android.quickstep.TaskAnimationManager; import com.android.quickstep.TaskViewUtils; @@ -79,10 +81,12 @@ public class SplitSelectStateController { private final Context mContext; private final Handler mHandler; + private final RecentsModel mRecentTasksModel; private StatsLogManager mStatsLogManager; private final SystemUiProxy mSystemUiProxy; private final StateManager mStateManager; - private final DepthController mDepthController; + @Nullable + private DepthController mDepthController; private @StagePosition int mStagePosition; private ItemInfo mItemInfo; private Intent mInitialTaskIntent; @@ -110,6 +114,7 @@ public class SplitSelectStateController { mSystemUiProxy = SystemUiProxy.INSTANCE.get(mContext); mStateManager = stateManager; mDepthController = depthController; + mRecentTasksModel = RecentsModel.INSTANCE.get(context); } /** @@ -148,6 +153,50 @@ public class SplitSelectStateController { mSplitEvent = splitEvent; } + /** + * Pulls the list of active Tasks from RecentsModel, and finds the most recently active Task + * matching a given ComponentName. Then uses that Task (which could be null) with the given + * callback. + * + * Used in various task-switching or splitscreen operations when we need to check if there is a + * currently running Task of a certain type and use the most recent one. + */ + public void findLastActiveTaskAndRunCallback(ComponentName componentName, + Consumer callback) { + mRecentTasksModel.getTasks(taskGroups -> { + Task lastActiveTask = null; + // Loop through tasks in reverse, since they are ordered with most-recent tasks last. + for (int i = taskGroups.size() - 1; i >= 0; i--) { + GroupTask groupTask = taskGroups.get(i); + Task task1 = groupTask.task1; + if (isInstanceOfComponent(task1, componentName)) { + lastActiveTask = task1; + break; + } + Task task2 = groupTask.task2; + if (isInstanceOfComponent(task2, componentName)) { + lastActiveTask = task2; + break; + } + } + + callback.accept(lastActiveTask); + }); + } + + /** + * Checks if a given Task is the most recently-active Task of type componentName. Used for + * selecting already-running Tasks for splitscreen. + */ + public boolean isInstanceOfComponent(@Nullable Task task, ComponentName componentName) { + // Exclude the task that is already staged + if (task == null || task.key.id == mInitialTaskId) { + return false; + } + + return task.key.baseIntent.getComponent().equals(componentName); + } + /** * To be called when the actual tasks ({@link #mInitialTaskId}, {@link #mSecondTaskId}) are * to be launched. Call after launcher side animations are complete. diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 5b408493b3..884da90dc8 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -1285,53 +1285,6 @@ public abstract class RecentsView callback) { - mModel.getTasks(taskGroups -> { - Task lastActiveTask = null; - // Loop through tasks in reverse, since they are ordered with most-recent tasks last. - for (int i = taskGroups.size() - 1; i >= 0; i--) { - GroupTask groupTask = taskGroups.get(i); - Task task1 = groupTask.task1; - if (isInstanceOfComponent(task1, componentName)) { - lastActiveTask = task1; - break; - } - Task task2 = groupTask.task2; - if (isInstanceOfComponent(task2, componentName)) { - lastActiveTask = task2; - break; - } - } - - callback.accept(lastActiveTask); - }); - } - - /** - * Checks if a given Task is the most recently-active Task of type componentName. Used for - * selecting already-running Tasks for splitscreen. - */ - public boolean isInstanceOfComponent(@Nullable Task task, ComponentName componentName) { - if (task == null) { - return false; - } - // Exclude the task that is already staged - if (mSplitHiddenTaskView != null && mSplitHiddenTaskView.getTask().equals(task)) { - return false; - } - - return task.key.baseIntent.getComponent().equals(componentName); - } - public void setOverviewStateEnabled(boolean enabled) { mOverviewStateEnabled = enabled; updateTaskStackListenerState();