Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c97bb460 authored by Vinit Nayak's avatar Vinit Nayak
Browse files

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
parent a75105ef
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -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<Task>) foundTask -> {
                foundTask -> {
                    if (foundTask != null) {
                        TaskView foundTaskView =
                                recents.getTaskViewByTaskId(foundTask.key.id);
+4 −4
Original line number Diff line number Diff line
@@ -174,9 +174,9 @@ public class TaskbarUIController {
        if (recentsView == null) {
            return;
        }
        recentsView.findLastActiveTaskAndRunCallback(
        recentsView.getSplitSelectController().findLastActiveTaskAndRunCallback(
                splitSelectSource.intent.getComponent(),
                (Consumer<Task>) 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<Task>) foundTask -> {
                foundTask -> {
                    if (foundTask != null) {
                        TaskView foundTaskView = recents.getTaskViewByTaskId(foundTask.key.id);
                        // TODO (b/266482558): This additional null check is needed because there
+12 −15
Original line number Diff line number Diff line
@@ -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<Task>) 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);
        }
+50 −1
Original line number Diff line number Diff line
@@ -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<Task> 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.
+0 −47
Original line number Diff line number Diff line
@@ -1285,53 +1285,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
        return null;
    }

    /**
     * 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<Task> 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();