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

Commit 1caf1f7a authored by Ats Jenk's avatar Ats Jenk Committed by Android (Google) Code Review
Browse files

Merge "Exit split if task moves to bubble via trampoline" into main

parents 6dc66003 438d181c
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -1085,6 +1085,8 @@ public class SplitScreenController implements SplitDragPolicy.Starter,
                return "FULLSCREEN_REQUEST";
                return "FULLSCREEN_REQUEST";
            case EXIT_REASON_DRAG_TO_FULLSCREEN:
            case EXIT_REASON_DRAG_TO_FULLSCREEN:
                return "EXIT_REASON_DRAG_TO_FULLSCREEN";
                return "EXIT_REASON_DRAG_TO_FULLSCREEN";
            case EXIT_REASON_CHILD_TASK_ENTER_BUBBLE:
                return "CHILD_TASK_ENTER_BUBBLE";
            default:
            default:
                return "unknown reason, reason int = " + exitReason;
                return "unknown reason, reason int = " + exitReason;
        }
        }
+39 −4
Original line number Original line Diff line number Diff line
@@ -491,7 +491,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                    this /*stageListenerCallbacks*/,
                    this /*stageListenerCallbacks*/,
                    mSyncQueue,
                    mSyncQueue,
                    iconProvider,
                    iconProvider,
                    mWindowDecorViewModel);
                    mWindowDecorViewModel,
                    mBubbleController);
        } else {
        } else {
            mMainStage = new StageTaskListener(
            mMainStage = new StageTaskListener(
                    mContext,
                    mContext,
@@ -500,7 +501,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                    this /*stageListenerCallbacks*/,
                    this /*stageListenerCallbacks*/,
                    mSyncQueue,
                    mSyncQueue,
                    iconProvider,
                    iconProvider,
                    mWindowDecorViewModel, STAGE_TYPE_MAIN);
                    mWindowDecorViewModel, STAGE_TYPE_MAIN,
                    bubbleController);
            mSideStage = new StageTaskListener(
            mSideStage = new StageTaskListener(
                    mContext,
                    mContext,
                    mTaskOrganizer,
                    mTaskOrganizer,
@@ -508,7 +510,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                    this /*stageListenerCallbacks*/,
                    this /*stageListenerCallbacks*/,
                    mSyncQueue,
                    mSyncQueue,
                    iconProvider,
                    iconProvider,
                    mWindowDecorViewModel, STAGE_TYPE_SIDE);
                    mWindowDecorViewModel, STAGE_TYPE_SIDE,
                    mBubbleController);
        }
        }
        mTransitions = transitions;
        mTransitions = transitions;
        mDisplayController = displayController;
        mDisplayController = displayController;
@@ -1747,7 +1750,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    /**
    /**
     * Starts a new transition to dismiss split.
     * Starts a new transition to dismiss split.
     */
     */
    private void dismissSplit(@StageType int stageToTop, @ExitReason int exitReason) {
    @VisibleForTesting
    void dismissSplit(@StageType int stageToTop, @ExitReason int exitReason) {
        if (!isSplitActive()) {
        if (!isSplitActive()) {
            return;
            return;
        }
        }
@@ -2361,6 +2365,37 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        }
        }
    }
    }


    @Override
    public void onChildTaskMovedToBubble(StageTaskListener stage, int taskId) {
        if (stage.getChildCount() != 0) {
            ProtoLog.d(WM_SHELL_SPLIT_SCREEN,
                    "onChildTaskMovedToBubble: task=%d in stage=%s moved to bubble, ignore, "
                            + "childCount=%d",
                    taskId, stageTypeToString(stage.getId()), stage.getChildCount());
            return;
        }
        int stageToTop = STAGE_TYPE_UNDEFINED;
        if (enableFlexibleSplit()) {
            for (StageTaskListener activeStage : mStageOrderOperator.getActiveStages()) {
                // See if any other stage still has children
                if (activeStage.getChildCount() > 0) {
                    stageToTop = activeStage.getId();
                    break;
                }
            }
        } else {
            final StageTaskListener remainingStage = stage == mMainStage ? mSideStage : mMainStage;
            if (remainingStage.getChildCount() > 0) {
                stageToTop = remainingStage.getId();
            }
        }
        ProtoLog.d(WM_SHELL_SPLIT_SCREEN,
                "onChildTaskMovedToBubble: taskId=%d in stage=%s moved to bubble exit split "
                        + "stageToTop=%s",
                taskId, stageTypeToString(stage.getId()), stageTypeToString(stageToTop));
        dismissSplit(stageToTop, EXIT_REASON_CHILD_TASK_ENTER_BUBBLE);
    }

    private void updateRecentTasksSplitPair() {
    private void updateRecentTasksSplitPair() {
        // Preventing from single task update while processing recents.
        // Preventing from single task update while processing recents.
        if (!mShouldUpdateRecents || !mPausingTasks.isEmpty()) {
        if (!mShouldUpdateRecents || !mPausingTasks.isEmpty()) {
+8 −4
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import android.content.Context
import com.android.internal.protolog.ProtoLog
import com.android.internal.protolog.ProtoLog
import com.android.launcher3.icons.IconProvider
import com.android.launcher3.icons.IconProvider
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.ShellTaskOrganizer
import com.android.wm.shell.bubbles.BubbleController
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.common.SyncTransactionQueue
import com.android.wm.shell.protolog.ShellProtoLogGroup
import com.android.wm.shell.protolog.ShellProtoLogGroup
import com.android.wm.shell.shared.split.SplitScreenConstants
import com.android.wm.shell.shared.split.SplitScreenConstants
@@ -52,7 +53,8 @@ class StageOrderOperator (
        stageCallbacks: StageTaskListener.StageListenerCallbacks,
        stageCallbacks: StageTaskListener.StageListenerCallbacks,
        syncQueue: SyncTransactionQueue,
        syncQueue: SyncTransactionQueue,
        iconProvider: IconProvider,
        iconProvider: IconProvider,
        windowDecorViewModel: Optional<WindowDecorViewModel>
        windowDecorViewModel: Optional<WindowDecorViewModel>,
        bubbleController: Optional<BubbleController>,
) {
) {


    private val MAX_STAGES = 3
    private val MAX_STAGES = 3
@@ -77,14 +79,16 @@ class StageOrderOperator (


    init {
    init {
        for(i in 0 until MAX_STAGES) {
        for(i in 0 until MAX_STAGES) {
            allStages.add(StageTaskListener(context,
            allStages.add(StageTaskListener(
                context,
                taskOrganizer,
                taskOrganizer,
                displayId,
                displayId,
                stageCallbacks,
                stageCallbacks,
                syncQueue,
                syncQueue,
                iconProvider,
                iconProvider,
                windowDecorViewModel,
                windowDecorViewModel,
                stageIds[i])
                stageIds[i],
                bubbleController)
            )
            )
        }
        }
    }
    }
+15 −3
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@ import static android.content.res.Configuration.SMALLEST_SCREEN_WIDTH_DP_UNDEFIN
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.RemoteAnimationTarget.MODE_OPENING;


import static com.android.wm.shell.Flags.enableFlexibleSplit;
import static com.android.wm.shell.Flags.enableFlexibleSplit;
import static com.android.wm.shell.Flags.fixExitSplitOnEnterBubble;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN;
import static com.android.wm.shell.protolog.ShellProtoLogGroup.WM_SHELL_SPLIT_SCREEN;
import static com.android.wm.shell.shared.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
import static com.android.wm.shell.shared.split.SplitScreenConstants.CONTROLLED_ACTIVITY_TYPES;
import static com.android.wm.shell.shared.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
import static com.android.wm.shell.shared.split.SplitScreenConstants.CONTROLLED_WINDOWING_MODES;
@@ -51,6 +52,7 @@ import com.android.internal.protolog.ProtoLog;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.ArrayUtils;
import com.android.launcher3.icons.IconProvider;
import com.android.launcher3.icons.IconProvider;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.common.SurfaceUtils;
import com.android.wm.shell.common.SurfaceUtils;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.SyncTransactionQueue;
import com.android.wm.shell.common.split.SplitDecorManager;
import com.android.wm.shell.common.split.SplitDecorManager;
@@ -93,6 +95,8 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
        void onChildTaskStatusChanged(StageTaskListener stage, int taskId, boolean present,
        void onChildTaskStatusChanged(StageTaskListener stage, int taskId, boolean present,
                boolean visible);
                boolean visible);


        /** Called when a child task vanished and is now in a bubble. */
        void onChildTaskMovedToBubble(StageTaskListener stage, int taskId);


        /** Called when the root task on current display vanishes. */
        /** Called when the root task on current display vanishes. */
        void onRootTaskVanished(ActivityManager.RunningTaskInfo taskInfo);
        void onRootTaskVanished(ActivityManager.RunningTaskInfo taskInfo);
@@ -106,6 +110,7 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
    private final SyncTransactionQueue mSyncQueue;
    private final SyncTransactionQueue mSyncQueue;
    private final IconProvider mIconProvider;
    private final IconProvider mIconProvider;
    private final Optional<WindowDecorViewModel> mWindowDecorViewModel;
    private final Optional<WindowDecorViewModel> mWindowDecorViewModel;
    private final Optional<BubbleController> mBubbleController;


    /** Whether or not the root task has been created. */
    /** Whether or not the root task has been created. */
    boolean mHasRootTask = false;
    boolean mHasRootTask = false;
@@ -124,12 +129,14 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
    StageTaskListener(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
    StageTaskListener(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
            StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
            StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
            IconProvider iconProvider,
            IconProvider iconProvider,
            Optional<WindowDecorViewModel> windowDecorViewModel, int id) {
            Optional<WindowDecorViewModel> windowDecorViewModel, int id,
            Optional<BubbleController> bubbleController) {
        mContext = context;
        mContext = context;
        mCallbacks = callbacks;
        mCallbacks = callbacks;
        mSyncQueue = syncQueue;
        mSyncQueue = syncQueue;
        mIconProvider = iconProvider;
        mIconProvider = iconProvider;
        mWindowDecorViewModel = windowDecorViewModel;
        mWindowDecorViewModel = windowDecorViewModel;
        mBubbleController = bubbleController;
        taskOrganizer.createRootTask(
        taskOrganizer.createRootTask(
                new TaskOrganizer.CreateRootTaskRequest()
                new TaskOrganizer.CreateRootTaskRequest()
                        .setName(stageTypeToString(id).toLowerCase())
                        .setName(stageTypeToString(id).toLowerCase())
@@ -334,8 +341,13 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
        } else if (mChildrenTaskInfo.contains(taskId)) {
        } else if (mChildrenTaskInfo.contains(taskId)) {
            mChildrenTaskInfo.remove(taskId);
            mChildrenTaskInfo.remove(taskId);
            mChildrenLeashes.remove(taskId);
            mChildrenLeashes.remove(taskId);
            if (fixExitSplitOnEnterBubble()
                    && mBubbleController.map(c -> c.shouldBeAppBubble(taskInfo)).orElse(false)) {
                mCallbacks.onChildTaskMovedToBubble(this, taskId);
            } else {
                mCallbacks.onChildTaskStatusChanged(this, taskId, false /* present */,
                mCallbacks.onChildTaskStatusChanged(this, taskId, false /* present */,
                        taskInfo.isVisible);
                        taskInfo.isVisible);
            }
        } else {
        } else {
            throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo
            throw new IllegalArgumentException(this + "\n Unknown task: " + taskInfo
                    + "\n mRootTaskInfo: " + mRootTaskInfo);
                    + "\n mRootTaskInfo: " + mRootTaskInfo);
+6 −2
Original line number Original line Diff line number Diff line
@@ -82,6 +82,7 @@ import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.TestShellExecutor;
import com.android.wm.shell.bubbles.BubbleController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayImeController;
import com.android.wm.shell.common.DisplayInsetsController;
import com.android.wm.shell.common.DisplayInsetsController;
@@ -138,6 +139,7 @@ public class SplitTransitionTests extends ShellTestCase {
    private FakeDesktopState mDesktopState;
    private FakeDesktopState mDesktopState;
    @Mock private IActivityTaskManager mActivityTaskManager;
    @Mock private IActivityTaskManager mActivityTaskManager;
    @Mock private MSDLPlayer mMSDLPlayer;
    @Mock private MSDLPlayer mMSDLPlayer;
    @Mock private BubbleController mBubbleController;
    private final TestShellExecutor mTestShellExecutor = new TestShellExecutor();
    private final TestShellExecutor mTestShellExecutor = new TestShellExecutor();
    private SplitLayout mSplitLayout;
    private SplitLayout mSplitLayout;
    private StageTaskListener mMainStage;
    private StageTaskListener mMainStage;
@@ -164,11 +166,13 @@ public class SplitTransitionTests extends ShellTestCase {
        mSplitLayout = SplitTestUtils.createMockSplitLayout();
        mSplitLayout = SplitTestUtils.createMockSplitLayout();
        mMainStage = spy(new StageTaskListener(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
        mMainStage = spy(new StageTaskListener(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
                StageTaskListener.StageListenerCallbacks.class), mSyncQueue,
                StageTaskListener.StageListenerCallbacks.class), mSyncQueue,
                mIconProvider, Optional.of(mWindowDecorViewModel), STAGE_TYPE_MAIN));
                mIconProvider, Optional.of(mWindowDecorViewModel), STAGE_TYPE_MAIN,
                Optional.of(mBubbleController)));
        mMainStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
        mMainStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
        mSideStage = spy(new StageTaskListener(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
        mSideStage = spy(new StageTaskListener(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
                StageTaskListener.StageListenerCallbacks.class), mSyncQueue,
                StageTaskListener.StageListenerCallbacks.class), mSyncQueue,
                mIconProvider, Optional.of(mWindowDecorViewModel), STAGE_TYPE_SIDE));
                mIconProvider, Optional.of(mWindowDecorViewModel), STAGE_TYPE_SIDE,
                Optional.of(mBubbleController)));
        mSideStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
        mSideStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
        mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY,
        mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY,
                mSyncQueue, mTaskOrganizer, mMainStage, mSideStage, mDisplayController,
                mSyncQueue, mTaskOrganizer, mMainStage, mSideStage, mDisplayController,
Loading