From 5289f17a805aa6f63f10a84c239a274cfd7137d2 Mon Sep 17 00:00:00 2001 From: Tony Huang Date: Mon, 27 Dec 2021 17:04:25 +0800 Subject: [PATCH] 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 --- .../wm/shell/splitscreen/SideStage.java | 6 ------ .../shell/splitscreen/StageCoordinator.java | 19 +++++++++++++++---- .../shell/splitscreen/StageTaskListener.java | 6 ++++++ .../com/android/server/wm/RunningTasks.java | 13 +++++++++++++ 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java index 1ba1d22e78311..122fc9f5f780c 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java @@ -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. diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java index 912e2a46fcbf3..53681e6b268f9 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java @@ -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); - // 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); + 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.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, diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java index 2c853c1c474c6..04e20db369eff 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java @@ -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); } diff --git a/services/core/java/com/android/server/wm/RunningTasks.java b/services/core/java/com/android/server/wm/RunningTasks.java index 7ba772c184551..9864297de5294 100644 --- a/services/core/java/com/android/server/wm/RunningTasks.java +++ b/services/core/java/com/android/server/wm/RunningTasks.java @@ -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);