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

Commit b78b1dfd authored by Jerry Chang's avatar Jerry Chang
Browse files

Consolidate entering split screen behavior

Add a fallback logic for entering split screen by verifying it contances
opening task to the indicated side to prevent leaving one side of the
split empty. Fix checking the wrong running task when entering split
screen by checking the top running task instead of checking reported
focusing task since the focusing task is not matching with the leaf task
running on top always.

Fix: 246689775
Fix: 260389099
Test: atest WMShellUnitTests
Test: drag and drop Calender to enter split while Calender on top won't
      leave empty side split.
Test: drag and drop Chrome to enter split while Chrome on top won't pup
      up not supported toast.
Change-Id: Ic7ea239b10ce41d956a85dbd6d04e007babd0743
parent 96c49780
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -341,6 +341,16 @@ public class RecentTasksController implements TaskStackListenerCallback,
        return recentTasks;
    }

    /**
     * Returns the top running leaf task.
     */
    @Nullable
    public ActivityManager.RunningTaskInfo getTopRunningTask() {
        List<ActivityManager.RunningTaskInfo> tasks = mActivityTaskManager.getTasks(1,
                false /* filterOnlyVisibleRecents */);
        return tasks.isEmpty() ? null : tasks.get(0);
    }

    /**
     * Find the background task that match the given component.
     */
+4 −7
Original line number Diff line number Diff line
@@ -315,10 +315,6 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        return mStageCoordinator;
    }

    public ActivityManager.RunningTaskInfo getFocusingTaskInfo() {
        return mStageCoordinator.getFocusingTaskInfo();
    }

    public boolean isValidToEnterSplitScreen(@NonNull ActivityManager.RunningTaskInfo taskInfo) {
        return mStageCoordinator.isValidToEnterSplitScreen(taskInfo);
    }
@@ -628,9 +624,10 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        if (!isSplitScreenVisible()) {
            // Split screen is not yet activated, check if the current top running task is valid to
            // split together.
            final ActivityManager.RunningTaskInfo taskInfo = getFocusingTaskInfo();
            if (taskInfo != null && isValidToEnterSplitScreen(taskInfo)) {
                return Objects.equals(taskInfo.baseIntent.getComponent(), launchingActivity);
            final ActivityManager.RunningTaskInfo topRunningTask = mRecentTasksOptional
                    .map(recentTasks -> recentTasks.getTopRunningTask()).orElse(null);
            if (topRunningTask != null && isValidToEnterSplitScreen(topRunningTask)) {
                return Objects.equals(topRunningTask.baseIntent.getComponent(), launchingActivity);
            }
            return false;
        }
+25 −29
Original line number Diff line number Diff line
@@ -150,7 +150,7 @@ import java.util.Optional;
 */
public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        DisplayController.OnDisplaysChangedListener, Transitions.TransitionHandler,
        ShellTaskOrganizer.TaskListener, ShellTaskOrganizer.FocusListener {
        ShellTaskOrganizer.TaskListener {

    private static final String TAG = StageCoordinator.class.getSimpleName();

@@ -186,8 +186,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    private final Rect mTempRect1 = new Rect();
    private final Rect mTempRect2 = new Rect();

    private ActivityManager.RunningTaskInfo mFocusingTaskInfo;

    /**
     * A single-top root task which the split divider attached to.
     */
@@ -304,7 +302,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        mDisplayController.addDisplayWindowListener(this);
        mDisplayLayout = new DisplayLayout(displayController.getDisplayLayout(displayId));
        transitions.addHandler(this);
        mTaskOrganizer.addFocusListener(this);
        mSplitUnsupportedToast = Toast.makeText(mContext,
                R.string.dock_non_resizeble_failed_to_dock_text, Toast.LENGTH_SHORT);
    }
@@ -455,8 +452,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    }

    /** Launches an activity into split by legacy transition. */
    void startIntentLegacy(PendingIntent intent, Intent fillInIntent,
            @SplitPosition int position, @Nullable Bundle options) {
    void startIntentLegacy(PendingIntent intent, Intent fillInIntent, @SplitPosition int position,
            @Nullable Bundle options) {
        final boolean isEnteringSplit = !isSplitActive();
        final WindowContainerTransaction evictWct = new WindowContainerTransaction();
        prepareEvictChildTasks(position, evictWct);

@@ -466,24 +464,31 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                    RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
                    IRemoteAnimationFinishedCallback finishedCallback,
                    SurfaceControl.Transaction t) {
                if (apps == null || apps.length == 0) {
                    if (mMainStage.getChildCount() == 0 || mSideStage.getChildCount() == 0) {
                        mMainExecutor.execute(() ->
                                exitSplitScreen(mMainStage.getChildCount() == 0
                                        ? mSideStage : mMainStage, EXIT_REASON_UNKNOWN));
                        mSplitUnsupportedToast.show();
                if (isEnteringSplit) {
                    boolean openingToSide = false;
                    if (apps != null) {
                        for (int i = 0; i < apps.length; ++i) {
                            if (apps[i].mode == MODE_OPENING
                                    && mSideStage.containsTask(apps[i].taskId)) {
                                openingToSide = true;
                                break;
                            }
                        }
                    }
                    if (!openingToSide) {
                        mMainExecutor.execute(() -> exitSplitScreen(
                                mSideStage.getChildCount() == 0 ? mMainStage : mSideStage,
                                EXIT_REASON_UNKNOWN));
                    }

                    // Do nothing when the animation was cancelled.
                    t.apply();
                    return;
                }

                if (apps != null) {
                    for (int i = 0; i < apps.length; ++i) {
                        if (apps[i].mode == MODE_OPENING) {
                            t.show(apps[i].leash);
                        }
                    }
                }
                t.apply();

                if (finishedCallback != null) {
@@ -503,7 +508,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,

        // If split still not active, apply windows bounds first to avoid surface reset to
        // wrong pos by SurfaceAnimator from wms.
        if (!mMainStage.isActive() && mLogger.isEnterRequestedByDrag()) {
        if (isEnteringSplit && mLogger.isEnterRequestedByDrag()) {
            updateWindowBounds(mSplitLayout, wct);
        }

@@ -1617,15 +1622,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                && ArrayUtils.contains(CONTROLLED_WINDOWING_MODES, taskInfo.getWindowingMode());
    }

    ActivityManager.RunningTaskInfo getFocusingTaskInfo() {
        return mFocusingTaskInfo;
    }

    @Override
    public void onFocusTaskChanged(ActivityManager.RunningTaskInfo taskInfo) {
        mFocusingTaskInfo = taskInfo;
    }

    @Override
    public void onSnappedToDismiss(boolean bottomOrRight, int reason) {
        final boolean mainStageToTop =
+6 −6
Original line number Diff line number Diff line
@@ -178,10 +178,10 @@ public class SplitScreenControllerTests extends ShellTestCase {
        Intent startIntent = createStartIntent("startActivity");
        PendingIntent pendingIntent =
                PendingIntent.getActivity(mContext, 0, startIntent, FLAG_IMMUTABLE);
        // Put the same component into focus task
        ActivityManager.RunningTaskInfo focusTaskInfo =
        // Put the same component to the top running task
        ActivityManager.RunningTaskInfo topRunningTask =
                createTaskInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, startIntent);
        doReturn(focusTaskInfo).when(mStageCoordinator).getFocusingTaskInfo();
        doReturn(topRunningTask).when(mRecentTasks).getTopRunningTask();
        doReturn(true).when(mStageCoordinator).isValidToEnterSplitScreen(any());

        mSplitScreenController.startIntent(pendingIntent, null, SPLIT_POSITION_TOP_OR_LEFT, null);
@@ -199,10 +199,10 @@ public class SplitScreenControllerTests extends ShellTestCase {
        Intent startIntent = createStartIntent("startActivity");
        PendingIntent pendingIntent =
                PendingIntent.getActivity(mContext, 0, startIntent, FLAG_IMMUTABLE);
        // Put the same component into focus task
        ActivityManager.RunningTaskInfo focusTaskInfo =
        // Put the same component to the top running task
        ActivityManager.RunningTaskInfo topRunningTask =
                createTaskInfo(WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD, startIntent);
        doReturn(focusTaskInfo).when(mStageCoordinator).getFocusingTaskInfo();
        doReturn(topRunningTask).when(mRecentTasks).getTopRunningTask();
        doReturn(true).when(mStageCoordinator).isValidToEnterSplitScreen(any());
        // Put the same component into a task in the background
        ActivityManager.RecentTaskInfo sameTaskInfo = new ActivityManager.RecentTaskInfo();