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
This commit is contained in:
Tony Huang
2021-12-27 17:04:25 +08:00
parent 7f0df9d84d
commit 5289f17a80
4 changed files with 34 additions and 10 deletions

View File

@@ -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.

View File

@@ -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,

View File

@@ -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);
}

View File

@@ -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);