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

Commit 5289f17a authored by Tony Huang's avatar Tony Huang
Browse files

Fix launcher crash and correct split behavior

Fix laucher crash while swipe up in split screen. This issue caused
by launcher will request 3 runningTaskInfos to do some action,
however, it cannot ensure 3 info actually include both splits because
only one got focused. Fix this by WA on RunningTasks, update the
adjacent task of the focus one too to make sure both split task
will be top two while calling getTasks.

Correct some split behavior while startTasksWithLegacyTransition
too.

Bug: 211716649
Test: pass existing tests.
Test: Make many split pair then swipe up
Change-Id: I2e6deb2ac607b454ca8fc760f0399135a1e8e901
Merged-In: I2e6deb2ac607b454ca8fc760f0399135a1e8e901
parent 7f0df9d8
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -19,7 +19,6 @@ package com.android.wm.shell.splitscreen;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.content.Context;
import android.graphics.Rect;
import android.view.SurfaceSession;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;
@@ -45,11 +44,6 @@ class SideStage extends StageTaskListener {
                stageTaskUnfoldController);
    }

    void moveToTop(Rect rootBounds, WindowContainerTransaction wct) {
        final WindowContainerToken rootToken = mRootTaskInfo.token;
        wct.setBounds(rootToken, rootBounds).reorder(rootToken, true /* onTop */);
    }

    boolean removeAllTasks(WindowContainerTransaction wct, boolean toTop) {
        // No matter if the root task is empty or not, moving the root to bottom because it no
        // longer preserves visible child task.
+15 −4
Original line number Diff line number Diff line
@@ -368,6 +368,9 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        // Init divider first to make divider leash for remote animation target.
        setDividerVisibility(true /* visible */);
        final WindowContainerTransaction wct = new WindowContainerTransaction();
        final WindowContainerTransaction evictWct = new WindowContainerTransaction();
        prepareEvictChildTasks(SPLIT_POSITION_TOP_OR_LEFT, evictWct);
        prepareEvictChildTasks(SPLIT_POSITION_BOTTOM_OR_RIGHT, evictWct);
        // Need to add another wrapper here in shell so that we can inject the divider bar
        // and also manage the process elevation via setRunningRemote
        IRemoteAnimationRunner wrapper = new IRemoteAnimationRunner.Stub() {
@@ -390,6 +393,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                            @Override
                            public void onAnimationFinished() throws RemoteException {
                                mIsDividerRemoteAnimating = false;
                                mSyncQueue.queue(evictWct);
                                mSyncQueue.runInSync(t -> applyDividerVisibility(t));
                                finishedCallback.onAnimationFinished();
                            }
@@ -412,6 +416,8 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            @Override
            public void onAnimationCancelled() {
                mIsDividerRemoteAnimating = false;
                mSyncQueue.queue(evictWct);
                mSyncQueue.runInSync(t -> applyDividerVisibility(t));
                try {
                    adapter.getRunner().onAnimationCancelled();
                } catch (RemoteException e) {
@@ -434,10 +440,14 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        setSideStagePosition(sidePosition, wct);

        mSplitLayout.setDivideRatio(splitRatio);
        if (mMainStage.isActive()) {
            mMainStage.moveToTop(getMainStageBounds(), wct);
        } else {
            // Build a request WCT that will launch both apps such that task 0 is on the main stage
            // while task 1 is on the side stage.
            mMainStage.activate(getMainStageBounds(), wct, false /* reparent */);
        mSideStage.setBounds(getSideStageBounds(), wct);
        }
        mSideStage.moveToTop(getSideStageBounds(), wct);

        // Make sure the launch options will put tasks in the corresponding split roots
        addActivityOptions(mainOptions, mMainStage);
@@ -902,6 +912,7 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,

        if (mDividerVisible) {
            t.show(dividerLeash)
                    .setAlpha(dividerLeash, 1)
                    .setLayer(dividerLeash, SPLIT_DIVIDER_LAYER)
                    .setPosition(dividerLeash,
                            mSplitLayout.getDividerBounds().left,
+6 −0
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import android.graphics.Rect;
import android.util.SparseArray;
import android.view.SurfaceControl;
import android.view.SurfaceSession;
import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;

import androidx.annotation.NonNull;
@@ -304,6 +305,11 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
        wct.reparent(task.token, mRootTaskInfo.token, true /* onTop*/);
    }

    void moveToTop(Rect rootBounds, WindowContainerTransaction wct) {
        final WindowContainerToken rootToken = mRootTaskInfo.token;
        wct.setBounds(rootToken, rootBounds).reorder(rootToken, true /* onTop */);
    }

    void setBounds(Rect bounds, WindowContainerTransaction wct) {
        wct.setBounds(mRootTaskInfo.token, bounds);
    }
+13 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ class RunningTasks {
    private boolean mAllowed;
    private boolean mFilterOnlyVisibleRecents;
    private Task mTopDisplayFocusRootTask;
    private Task mTopDisplayAdjacentTask;
    private RecentTasks mRecentTasks;
    private boolean mKeepIntentExtra;

@@ -77,6 +78,12 @@ class RunningTasks {
        mRecentTasks = root.mService.getRecentTasks();
        mKeepIntentExtra = (flags & FLAG_KEEP_INTENT_EXTRA) == FLAG_KEEP_INTENT_EXTRA;

        if (mTopDisplayFocusRootTask.getAdjacentTaskFragment() != null) {
            mTopDisplayAdjacentTask = mTopDisplayFocusRootTask.getAdjacentTaskFragment().asTask();
        } else {
            mTopDisplayAdjacentTask = null;
        }

        final PooledConsumer c = PooledLambda.obtainConsumer(RunningTasks::processTask, this,
                PooledLambda.__(Task.class));
        root.forAllLeafTasks(c, false);
@@ -126,6 +133,12 @@ class RunningTasks {
            // can be used to determine the order of the tasks (it may not be set for newly
            // created tasks)
            task.touchActiveTime();
        } else if (rootTask == mTopDisplayAdjacentTask && rootTask.getTopMostTask() == task) {
            // The short-term workaround for launcher could get suitable running task info in
            // split screen.
            task.touchActiveTime();
            // TreeSet doesn't allow same value and make sure this task is lower than focus one.
            task.lastActiveTime--;
        }

        mTmpSortedSet.add(task);