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

Commit 8f7d2534 authored by Winson Chung's avatar Winson Chung Committed by Android (Google) Code Review
Browse files

Merge "Update recent tasks split pairs from split controller" into sc-v2-dev

parents 6bd4a663 6be95d2f
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -240,8 +240,12 @@ public abstract class WMShellBaseModule {
    @WMSingleton
    @Provides
    static FullscreenTaskListener provideFullscreenTaskListener(
            SyncTransactionQueue syncQueue, Optional<FullscreenUnfoldController> controller) {
        return new FullscreenTaskListener(syncQueue, controller);
            SyncTransactionQueue syncQueue,
            Optional<FullscreenUnfoldController> optionalFullscreenUnfoldController,
            Optional<RecentTasksController> recentTasksOptional
    ) {
        return new FullscreenTaskListener(syncQueue, optionalFullscreenUnfoldController,
                recentTasksOptional);
    }

    //
@@ -490,12 +494,13 @@ public abstract class WMShellBaseModule {
            DisplayImeController displayImeController,
            DisplayInsetsController displayInsetsController, Transitions transitions,
            TransactionPool transactionPool, IconProvider iconProvider,
            Optional<RecentTasksController> recentTasks,
            Provider<Optional<StageTaskUnfoldController>> stageTaskUnfoldControllerProvider) {
        if (ActivityTaskManager.supportsSplitScreenMultiWindow(context)) {
            return Optional.of(new SplitScreenController(shellTaskOrganizer, syncQueue, context,
                    rootTaskDisplayAreaOrganizer, mainExecutor, displayImeController,
                    displayInsetsController, transitions, transactionPool, iconProvider,
                    stageTaskUnfoldControllerProvider));
                    recentTasks, stageTaskUnfoldControllerProvider));
        } else {
            return Optional.empty();
        }
+21 −1
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.internal.protolog.common.ProtoLog;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.transition.Transitions;

import java.io.PrintWriter;
@@ -47,15 +48,23 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
    private static final String TAG = "FullscreenTaskListener";

    private final SyncTransactionQueue mSyncQueue;
    private final FullscreenUnfoldController mFullscreenUnfoldController;
    private final Optional<RecentTasksController> mRecentTasksOptional;

    private final SparseArray<TaskData> mDataByTaskId = new SparseArray<>();
    private final AnimatableTasksListener mAnimatableTasksListener = new AnimatableTasksListener();
    private final FullscreenUnfoldController mFullscreenUnfoldController;

    public FullscreenTaskListener(SyncTransactionQueue syncQueue,
            Optional<FullscreenUnfoldController> unfoldController) {
        this(syncQueue, unfoldController, Optional.empty());
    }

    public FullscreenTaskListener(SyncTransactionQueue syncQueue,
            Optional<FullscreenUnfoldController> unfoldController,
            Optional<RecentTasksController> recentTasks) {
        mSyncQueue = syncQueue;
        mFullscreenUnfoldController = unfoldController.orElse(null);
        mRecentTasksOptional = recentTasks;
    }

    @Override
@@ -79,6 +88,7 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
        });

        mAnimatableTasksListener.onTaskAppeared(taskInfo);
        updateRecentsForVisibleFullscreenTask(taskInfo);
    }

    @Override
@@ -86,6 +96,7 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
        if (Transitions.ENABLE_SHELL_TRANSITIONS) return;

        mAnimatableTasksListener.onTaskInfoChanged(taskInfo);
        updateRecentsForVisibleFullscreenTask(taskInfo);

        final TaskData data = mDataByTaskId.get(taskInfo.taskId);
        final Point positionInParent = taskInfo.positionInParent;
@@ -111,6 +122,15 @@ public class FullscreenTaskListener implements ShellTaskOrganizer.TaskListener {
                taskInfo.taskId);
    }

    private void updateRecentsForVisibleFullscreenTask(RunningTaskInfo taskInfo) {
        mRecentTasksOptional.ifPresent(recentTasks -> {
            if (taskInfo.isVisible) {
                // Remove any persisted splits if either tasks are now made fullscreen and visible
                recentTasks.removeSplitPair(taskInfo.taskId);
            }
        });
    }

    @Override
    public void attachChildSurfaceToTask(int taskId, SurfaceControl.Builder b) {
        if (!mDataByTaskId.contains(taskId)) {
+18 −1
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ import com.android.wm.shell.common.TransactionPool;
import com.android.wm.shell.common.annotations.ExternalThread;
import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
import com.android.wm.shell.draganddrop.DragAndDropPolicy;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.transition.LegacyTransitions;
import com.android.wm.shell.transition.Transitions;

@@ -124,10 +125,12 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
    private final TransactionPool mTransactionPool;
    private final SplitscreenEventLogger mLogger;
    private final IconProvider mIconProvider;
    private final Optional<RecentTasksController> mRecentTasksOptional;
    private final Provider<Optional<StageTaskUnfoldController>> mUnfoldControllerProvider;

    private StageCoordinator mStageCoordinator;

    // TODO(b/205019015): Remove after we clean up downstream modules
    public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer,
            SyncTransactionQueue syncQueue, Context context,
            RootTaskDisplayAreaOrganizer rootTDAOrganizer,
@@ -135,6 +138,19 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
            DisplayInsetsController displayInsetsController,
            Transitions transitions, TransactionPool transactionPool, IconProvider iconProvider,
            Provider<Optional<StageTaskUnfoldController>> unfoldControllerProvider) {
        this(shellTaskOrganizer, syncQueue, context, rootTDAOrganizer, mainExecutor,
                displayImeController, displayInsetsController, transitions, transactionPool,
                iconProvider, Optional.empty(), unfoldControllerProvider);
    }

    public SplitScreenController(ShellTaskOrganizer shellTaskOrganizer,
            SyncTransactionQueue syncQueue, Context context,
            RootTaskDisplayAreaOrganizer rootTDAOrganizer,
            ShellExecutor mainExecutor, DisplayImeController displayImeController,
            DisplayInsetsController displayInsetsController,
            Transitions transitions, TransactionPool transactionPool, IconProvider iconProvider,
            Optional<RecentTasksController> recentTasks,
            Provider<Optional<StageTaskUnfoldController>> unfoldControllerProvider) {
        mTaskOrganizer = shellTaskOrganizer;
        mSyncQueue = syncQueue;
        mContext = context;
@@ -147,6 +163,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        mUnfoldControllerProvider = unfoldControllerProvider;
        mLogger = new SplitscreenEventLogger();
        mIconProvider = iconProvider;
        mRecentTasksOptional = recentTasks;
    }

    public SplitScreen asSplitScreen() {
@@ -169,7 +186,7 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
            mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
                    mRootTDAOrganizer, mTaskOrganizer, mDisplayImeController,
                    mDisplayInsetsController, mTransitions, mTransactionPool, mLogger,
                    mIconProvider, mUnfoldControllerProvider);
                    mIconProvider, mRecentTasksOptional, mUnfoldControllerProvider);
        }
    }

+64 −6
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package com.android.wm.shell.splitscreen;

import static android.app.ActivityOptions.KEY_LAUNCH_ROOT_TASK_TOKEN;
import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.TRANSIT_OPEN;
@@ -92,6 +93,7 @@ import com.android.wm.shell.common.split.SplitLayout;
import com.android.wm.shell.common.split.SplitLayout.SplitPosition;
import com.android.wm.shell.common.split.SplitWindowManager;
import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.splitscreen.SplitScreenController.ExitReason;
import com.android.wm.shell.transition.Transitions;

@@ -147,6 +149,10 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    private final DisplayInsetsController mDisplayInsetsController;
    private final SplitScreenTransitions mSplitTransitions;
    private final SplitscreenEventLogger mLogger;
    private final Optional<RecentTasksController> mRecentTasks;
    // Tracks whether we should update the recent tasks.  Only allow this to happen in between enter
    // and exit, since exit itself can trigger a number of changes that update the stages.
    private boolean mShouldUpdateRecents;
    private boolean mExitSplitScreenOnHide;
    private boolean mKeyguardOccluded;

@@ -191,6 +197,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            DisplayInsetsController displayInsetsController, Transitions transitions,
            TransactionPool transactionPool, SplitscreenEventLogger logger,
            IconProvider iconProvider,
            Optional<RecentTasksController> recentTasks,
            Provider<Optional<StageTaskUnfoldController>> unfoldControllerProvider) {
        mContext = context;
        mDisplayId = displayId;
@@ -198,6 +205,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        mRootTDAOrganizer = rootTDAOrganizer;
        mTaskOrganizer = taskOrganizer;
        mLogger = logger;
        mRecentTasks = recentTasks;
        mMainUnfoldController = unfoldControllerProvider.get().orElse(null);
        mSideUnfoldController = unfoldControllerProvider.get().orElse(null);

@@ -238,6 +246,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            DisplayInsetsController displayInsetsController, SplitLayout splitLayout,
            Transitions transitions, TransactionPool transactionPool,
            SplitscreenEventLogger logger,
            Optional<RecentTasksController> recentTasks,
            Provider<Optional<StageTaskUnfoldController>> unfoldControllerProvider) {
        mContext = context;
        mDisplayId = displayId;
@@ -255,6 +264,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        mMainUnfoldController = unfoldControllerProvider.get().orElse(null);
        mSideUnfoldController = unfoldControllerProvider.get().orElse(null);
        mLogger = logger;
        mRecentTasks = recentTasks;
        transitions.addHandler(this);
    }

@@ -560,12 +570,23 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,

    private void applyExitSplitScreen(StageTaskListener childrenToTop,
            WindowContainerTransaction wct, @ExitReason int exitReason) {
        mRecentTasks.ifPresent(recentTasks -> {
            // Notify recents if we are exiting in a way that breaks the pair, and disable further
            // updates to splits in the recents until we enter split again
            if (shouldBreakPairedTaskInRecents(exitReason) && mShouldUpdateRecents) {
                recentTasks.removeSplitPair(mMainStage.getTopVisibleChildTaskId());
                recentTasks.removeSplitPair(mSideStage.getTopVisibleChildTaskId());
            }
        });
        mShouldUpdateRecents = false;

        mSideStage.removeAllTasks(wct, childrenToTop == mSideStage);
        mMainStage.deactivate(wct, childrenToTop == mMainStage);
        mTaskOrganizer.applyTransaction(wct);
        mSyncQueue.runInSync(t -> t
                .setWindowCrop(mMainStage.mRootLeash, null)
                .setWindowCrop(mSideStage.mRootLeash, null));

        // Hide divider and reset its position.
        setDividerVisibility(false);
        mSplitLayout.resetDividerPosition();
@@ -579,6 +600,23 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        }
    }

    /**
     * Returns whether the split pair in the recent tasks list should be broken.
     */
    private boolean shouldBreakPairedTaskInRecents(@ExitReason int exitReason) {
        switch (exitReason) {
            // One of the apps doesn't support MW
            case EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW:
            // User has explicitly dragged the divider to dismiss split
            case EXIT_REASON_DRAG_DIVIDER:
            // Either of the split apps have finished
            case EXIT_REASON_APP_FINISHED:
                return true;
            default:
                return false;
        }
    }

    /**
     * Unlike exitSplitScreen, this takes a stagetype vs an actual stage-reference and populates
     * an existing WindowContainerTransaction (rather than applying immediately). This is intended
@@ -645,12 +683,28 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            mLogger.logSideStageAppChange(getSideStagePosition(), mSideStage.getTopChildTaskUid(),
                    mSplitLayout.isLandscape());
        }
        updateRecentTasksSplitPair();

        for (int i = mListeners.size() - 1; i >= 0; --i) {
            mListeners.get(i).onTaskStageChanged(taskId, stage, visible);
        }
    }

    private void updateRecentTasksSplitPair() {
        if (!mShouldUpdateRecents) {
            return;
        }

        mRecentTasks.ifPresent(recentTasks -> {
            int mainStageTopTaskId = mMainStage.getTopVisibleChildTaskId();
            int sideStageTopTaskId = mSideStage.getTopVisibleChildTaskId();
            if (mainStageTopTaskId != INVALID_TASK_ID && sideStageTopTaskId != INVALID_TASK_ID) {
                // Update the pair for the top tasks
                recentTasks.addSplitPair(mainStageTopTaskId, sideStageTopTaskId);
            }
        });
    }

    private void sendSplitVisibilityChanged() {
        for (int i = mListeners.size() - 1; i >= 0; --i) {
            final SplitScreen.SplitScreenListener l = mListeners.get(i);
@@ -784,14 +838,18 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            mSyncQueue.queue(wct);
            mSyncQueue.runInSync(t -> updateSurfaceBounds(mSplitLayout, t));
        }
        if (!mLogger.hasStartedSession() && mMainStageListener.mHasChildren
                && mSideStageListener.mHasChildren) {
        if (mMainStageListener.mHasChildren && mSideStageListener.mHasChildren) {
            mShouldUpdateRecents = true;
            updateRecentTasksSplitPair();

            if (!mLogger.hasStartedSession()) {
                mLogger.logEnter(mSplitLayout.getDividerPositionAsFraction(),
                        getMainStagePosition(), mMainStage.getTopChildTaskUid(),
                        getSideStagePosition(), mSideStage.getTopChildTaskUid(),
                        mSplitLayout.isLandscape());
            }
        }
    }

    @VisibleForTesting
    IBinder onSnappedToDismissTransition(boolean mainStageToTop) {
+14 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.wm.shell.splitscreen;

import static android.app.ActivityTaskManager.INVALID_TASK_ID;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
@@ -112,6 +113,19 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
        return mChildrenTaskInfo.contains(taskId);
    }

    /**
     * Returns the top visible child task's id.
     */
    int getTopVisibleChildTaskId() {
        for (int i = mChildrenTaskInfo.size() - 1; i >= 0; --i) {
            final ActivityManager.RunningTaskInfo info = mChildrenTaskInfo.valueAt(i);
            if (info.isVisible) {
                return info.taskId;
            }
        }
        return INVALID_TASK_ID;
    }

    /**
     * Returns the top activity uid for the top child task.
     */
Loading