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

Commit 1c6b58ef authored by Tony Huang's avatar Tony Huang
Browse files

Fix split overlay by drag drop launch

When drag drop launch, wms will use animation leash to do launch
transition, and reparent surface back and reset its position by
windows its configuration.
However, on split side we also set windows bounds in same time,
so in some race condition, wms side reset its position later and
use old configuration because we update it in same time then cause
task surface position wrong.
To fix this issue, we should apply windows bounds before we launch
the intent.

This CL also fix divider invisible issue when drag drop some specfic
app to active split screen caused by surface tanscation race too.

Fix: 227142506
Fix: 240638389
Test: manual
Test: pass existing tests.
Change-Id: Ia195f39fbf8879cbee9608f0c27f98df7e9e289f
parent 4d334f45
Loading
Loading
Loading
Loading
+1 −52
Original line number Diff line number Diff line
@@ -21,7 +21,6 @@ import static android.app.ActivityManager.START_TASK_TO_FRONT;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NO_USER_ACTION;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.RemoteAnimationTarget.MODE_OPENING;

import static com.android.wm.shell.common.ExecutorUtils.executeRemoteCallWithTaskPermission;
import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_BOTTOM_OR_RIGHT;
@@ -86,7 +85,6 @@ import com.android.wm.shell.splitscreen.SplitScreen.StageType;
import com.android.wm.shell.sysui.KeyguardChangeListener;
import com.android.wm.shell.sysui.ShellController;
import com.android.wm.shell.sysui.ShellInit;
import com.android.wm.shell.transition.LegacyTransitions;
import com.android.wm.shell.transition.Transitions;

import java.io.PrintWriter;
@@ -411,62 +409,13 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
        }

        if (!ENABLE_SHELL_TRANSITIONS) {
            startIntentLegacy(intent, fillInIntent, position, options);
            mStageCoordinator.startIntentLegacy(intent, fillInIntent, position, options);
            return;
        }

        mStageCoordinator.startIntent(intent, fillInIntent, position, options);
    }

    private void startIntentLegacy(PendingIntent intent, Intent fillInIntent,
            @SplitPosition int position, @Nullable Bundle options) {
        final WindowContainerTransaction evictWct = new WindowContainerTransaction();
        mStageCoordinator.prepareEvictChildTasks(position, evictWct);

        LegacyTransitions.ILegacyTransition transition = new LegacyTransitions.ILegacyTransition() {
            @Override
            public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
                    RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
                    IRemoteAnimationFinishedCallback finishedCallback,
                    SurfaceControl.Transaction t) {
                if (apps == null || apps.length == 0) {
                    // Switch the split position if launching as MULTIPLE_TASK failed.
                    if ((fillInIntent.getFlags() & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
                        setSideStagePosition(SplitLayout.reversePosition(
                                mStageCoordinator.getSideStagePosition()));
                    }

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

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

                if (finishedCallback != null) {
                    try {
                        finishedCallback.onAnimationFinished();
                    } catch (RemoteException e) {
                        Slog.e(TAG, "Error finishing legacy transition: ", e);
                    }
                }

                mSyncQueue.queue(evictWct);
            }
        };

        final WindowContainerTransaction wct = new WindowContainerTransaction();
        options = mStageCoordinator.resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, wct);

        wct.sendPendingIntent(intent, fillInIntent, options);
        mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
    }

    /** Returns {@code true} if it's launching the same component on both sides of the split. */
    @VisibleForTesting
    boolean isLaunchingAdjacently(@Nullable Intent startIntent,
+66 −3
Original line number Diff line number Diff line
@@ -26,6 +26,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.RemoteAnimationTarget.MODE_OPENING;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_TO_BACK;
@@ -118,6 +119,7 @@ import com.android.wm.shell.protolog.ShellProtoLogGroup;
import com.android.wm.shell.recents.RecentTasksController;
import com.android.wm.shell.splitscreen.SplitScreen.StageType;
import com.android.wm.shell.splitscreen.SplitScreenController.ExitReason;
import com.android.wm.shell.transition.LegacyTransitions;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.util.SplitBounds;

@@ -195,7 +197,6 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
    private boolean mExitSplitScreenOnHide;
    private boolean mIsDividerRemoteAnimating;
    private boolean mIsExiting;
    private boolean mResizingSplits;

    /** The target stage to dismiss to when unlock after folded. */
    @StageType
@@ -210,8 +211,12 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,

                @Override
                public void onLeashReady(SurfaceControl leash) {
                    // This is for avoiding divider invisible due to delay of creating so only need
                    // to do when divider should visible case.
                    if (mDividerVisible) {
                        mSyncQueue.runInSync(t -> applyDividerVisibility(t));
                    }
                }
            };

    private final SplitScreenTransitions.TransitionCallback mRecentTransitionCallback =
@@ -433,6 +438,63 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                });
    }

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

        LegacyTransitions.ILegacyTransition transition = new LegacyTransitions.ILegacyTransition() {
            @Override
            public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
                    RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
                    IRemoteAnimationFinishedCallback finishedCallback,
                    SurfaceControl.Transaction t) {
                if (apps == null || apps.length == 0) {
                    // Switch the split position if launching as MULTIPLE_TASK failed.
                    if ((fillInIntent.getFlags() & FLAG_ACTIVITY_MULTIPLE_TASK) != 0) {
                        setSideStagePosition(SplitLayout.reversePosition(
                                getSideStagePosition()), null);
                    }

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

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

                if (finishedCallback != null) {
                    try {
                        finishedCallback.onAnimationFinished();
                    } catch (RemoteException e) {
                        Slog.e(TAG, "Error finishing legacy transition: ", e);
                    }
                }

                mSyncQueue.queue(evictWct);
            }
        };

        final WindowContainerTransaction wct = new WindowContainerTransaction();
        options = resolveStartStage(STAGE_TYPE_UNDEFINED, position, options, wct);

        // If split still not active, apply windows bounds first to avoid surface reset to
        // wrong pos by SurfaceAnimator from wms.
        // TODO(b/223325631): check  is it still necessary after improve enter transition done.
        if (!mMainStage.isActive()) {
            updateWindowBounds(mSplitLayout, wct);
        }

        wct.sendPendingIntent(intent, fillInIntent, options);
        mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
    }

    /** Starts 2 tasks in one transition. */
    void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId,
            @Nullable Bundle sideOptions, @SplitPosition int sidePosition, float splitRatio,
@@ -849,6 +911,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                    .setWindowCrop(mSideStage.mRootLeash, null);
            t.setPosition(mMainStage.mRootLeash, 0, 0)
                    .setPosition(mSideStage.mRootLeash, 0, 0);
            t.hide(mMainStage.mDimLayer).hide(mSideStage.mDimLayer);
            setDividerVisibility(false, t);

            // In this case, exit still under progress, fade out the split decor after first WCT
@@ -858,7 +921,7 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
                    WindowContainerTransaction finishedWCT = new WindowContainerTransaction();
                    mIsExiting = false;
                    childrenToTop.dismiss(finishedWCT, true /* toTop */);
                    wct.reorder(mRootTaskInfo.token, false /* toTop */);
                    finishedWCT.reorder(mRootTaskInfo.token, false /* toTop */);
                    mTaskOrganizer.applyTransaction(finishedWCT);
                    onTransitionAnimationComplete();
                });