Fix drop to enter split not working
Sometimes when dropping app icon to enter split screen, it'll exit split screen immediatlly because it evicts newly launched task before the task considered to be visible. Update to collect child tasks to evict before launching activity. Fix: 203610931 Fix: 203636251 Test: atest WMShellUnitTests Change-Id: If070fb5b3eb0b3fc178122d38b2dce3072621449
This commit is contained in:
@@ -215,10 +215,12 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
||||
options = mStageCoordinator.resolveStartStage(stage, position, options, null /* wct */);
|
||||
|
||||
try {
|
||||
final WindowContainerTransaction evictWct = new WindowContainerTransaction();
|
||||
mStageCoordinator.prepareEvictChildTasks(position, evictWct);
|
||||
final int result =
|
||||
ActivityTaskManager.getService().startActivityFromRecents(taskId, options);
|
||||
if (result == START_SUCCESS || result == START_TASK_TO_FRONT) {
|
||||
mStageCoordinator.evictOccludedChildren(position);
|
||||
mSyncQueue.queue(evictWct);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
Slog.e(TAG, "Failed to launch task", e);
|
||||
@@ -229,13 +231,15 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
||||
@SplitScreen.StageType int stage, @SplitPosition int position,
|
||||
@Nullable Bundle options, UserHandle user) {
|
||||
options = mStageCoordinator.resolveStartStage(stage, position, options, null /* wct */);
|
||||
final WindowContainerTransaction evictWct = new WindowContainerTransaction();
|
||||
mStageCoordinator.prepareEvictChildTasks(position, evictWct);
|
||||
|
||||
try {
|
||||
LauncherApps launcherApps =
|
||||
mContext.getSystemService(LauncherApps.class);
|
||||
launcherApps.startShortcut(packageName, shortcutId, null /* sourceBounds */,
|
||||
options, user);
|
||||
mStageCoordinator.evictOccludedChildren(position);
|
||||
mSyncQueue.queue(evictWct);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Slog.e(TAG, "Failed to launch shortcut", e);
|
||||
}
|
||||
@@ -255,6 +259,9 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
||||
private void startIntentLegacy(PendingIntent intent, Intent fillInIntent,
|
||||
@SplitScreen.StageType int stage, @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,
|
||||
@@ -280,12 +287,11 @@ public class SplitScreenController implements DragAndDropPolicy.Starter,
|
||||
}
|
||||
}
|
||||
|
||||
// Launching a new app into a specific split evicts tasks previously in the same
|
||||
// split.
|
||||
mStageCoordinator.evictOccludedChildren(position);
|
||||
mSyncQueue.queue(evictWct);
|
||||
}
|
||||
};
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
options = mStageCoordinator.resolveStartStage(stage, position, options, wct);
|
||||
wct.sendPendingIntent(intent, fillInIntent, options);
|
||||
mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
|
||||
|
||||
@@ -394,10 +394,16 @@ class StageCoordinator implements SplitLayout.SplitLayoutHandler,
|
||||
TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE, wct, remoteTransition, this);
|
||||
}
|
||||
|
||||
void evictOccludedChildren(@SplitPosition int position) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
(position == mSideStagePosition ? mSideStage : mMainStage).evictOccludedChildren(wct);
|
||||
mTaskOrganizer.applyTransaction(wct);
|
||||
/**
|
||||
* Collects all the current child tasks of a specific split and prepares transaction to evict
|
||||
* them to display.
|
||||
*/
|
||||
void prepareEvictChildTasks(@SplitPosition int position, WindowContainerTransaction wct) {
|
||||
if (position == mSideStagePosition) {
|
||||
mSideStage.evictAllChildren(wct);
|
||||
} else {
|
||||
mMainStage.evictAllChildren(wct);
|
||||
}
|
||||
}
|
||||
|
||||
Bundle resolveStartStage(@SplitScreen.StageType int stage,
|
||||
|
||||
@@ -248,12 +248,11 @@ class StageTaskListener implements ShellTaskOrganizer.TaskListener {
|
||||
wct.reorder(mChildrenTaskInfo.get(taskId).token, onTop /* onTop */);
|
||||
}
|
||||
|
||||
void evictOccludedChildren(WindowContainerTransaction wct) {
|
||||
/** Collects all the current child tasks and prepares transaction to evict them to display. */
|
||||
void evictAllChildren(WindowContainerTransaction wct) {
|
||||
for (int i = mChildrenTaskInfo.size() - 1; i >= 0; i--) {
|
||||
final ActivityManager.RunningTaskInfo taskInfo = mChildrenTaskInfo.valueAt(i);
|
||||
if (!taskInfo.isVisible) {
|
||||
wct.reparent(taskInfo.token, null /* parent */, false /* onTop */);
|
||||
}
|
||||
wct.reparent(taskInfo.token, null /* parent */, false /* onTop */);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@ import static android.view.Display.DEFAULT_DISPLAY;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assume.assumeFalse;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.clearInvocations;
|
||||
@@ -31,6 +33,7 @@ import android.app.ActivityManager;
|
||||
import android.os.SystemProperties;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.SurfaceSession;
|
||||
import android.window.WindowContainerTransaction;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -50,7 +53,7 @@ import org.mockito.MockitoAnnotations;
|
||||
/**
|
||||
* Tests for {@link StageTaskListener}
|
||||
* Build/Install/Run:
|
||||
* atest WMShellUnitTests:StageTaskListenerTests
|
||||
* atest WMShellUnitTests:StageTaskListenerTests
|
||||
*/
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@@ -58,11 +61,16 @@ public final class StageTaskListenerTests {
|
||||
private static final boolean ENABLE_SHELL_TRANSITIONS =
|
||||
SystemProperties.getBoolean("persist.debug.shell_transit", false);
|
||||
|
||||
@Mock private ShellTaskOrganizer mTaskOrganizer;
|
||||
@Mock private StageTaskListener.StageListenerCallbacks mCallbacks;
|
||||
@Mock private SyncTransactionQueue mSyncQueue;
|
||||
@Mock private StageTaskUnfoldController mStageTaskUnfoldController;
|
||||
@Captor private ArgumentCaptor<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor;
|
||||
@Mock
|
||||
private ShellTaskOrganizer mTaskOrganizer;
|
||||
@Mock
|
||||
private StageTaskListener.StageListenerCallbacks mCallbacks;
|
||||
@Mock
|
||||
private SyncTransactionQueue mSyncQueue;
|
||||
@Mock
|
||||
private StageTaskUnfoldController mStageTaskUnfoldController;
|
||||
@Captor
|
||||
private ArgumentCaptor<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor;
|
||||
private SurfaceSession mSurfaceSession = new SurfaceSession();
|
||||
private SurfaceControl mSurfaceControl;
|
||||
private ActivityManager.RunningTaskInfo mRootTask;
|
||||
@@ -167,4 +175,18 @@ public final class StageTaskListenerTests {
|
||||
mStageTaskListener.onTaskInfoChanged(childTask);
|
||||
verify(mCallbacks).onNoLongerSupportMultiWindow();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEvictAllChildren() {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mStageTaskListener.evictAllChildren(wct);
|
||||
assertTrue(wct.isEmpty());
|
||||
|
||||
final ActivityManager.RunningTaskInfo childTask =
|
||||
new TestRunningTaskInfoBuilder().setParentTaskId(mRootTask.taskId).build();
|
||||
mStageTaskListener.onTaskAppeared(childTask, mSurfaceControl);
|
||||
|
||||
mStageTaskListener.evictAllChildren(wct);
|
||||
assertFalse(wct.isEmpty());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user