Merge "Quickswitch with staged split" into sc-v2-dev am: 461a6cffd9

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/15728604

Change-Id: Ifb057db89ba77a81d7989a53f278df5ed8142de4
This commit is contained in:
Vinit Nayak
2021-09-02 22:58:21 +00:00
committed by Automerger Merge Worker
8 changed files with 89 additions and 15 deletions
@@ -297,7 +297,7 @@ public abstract class BaseQuickstepLauncher extends Launcher
mActionsView = findViewById(R.id.overview_actions_view);
RecentsView overviewPanel = (RecentsView) getOverviewPanel();
SplitSelectStateController controller =
new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this));
new SplitSelectStateController(SystemUiProxy.INSTANCE.get(this));
overviewPanel.init(mActionsView, controller);
mActionsView.setDp(getDeviceProfile());
mActionsView.updateVerticalMargin(SysUINavigationMode.getMode(this));
@@ -531,7 +531,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>,
ActivityManager.RunningTaskInfo[] runningTasks;
if (mIsSwipeForStagedSplit) {
int[] splitTaskIds =
LauncherSplitScreenListener.INSTANCE.getNoCreate().getSplitTaskIds();
LauncherSplitScreenListener.INSTANCE.getNoCreate().getRunningSplitTaskIds();
runningTasks = new ActivityManager.RunningTaskInfo[splitTaskIds.length];
for (int i = 0; i < splitTaskIds.length; i++) {
int taskId = splitTaskIds[i];
@@ -122,7 +122,7 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
SYSUI_PROGRESS.set(getRootView().getSysUiScrim(), 0f);
SplitSelectStateController controller =
new SplitSelectStateController(mHandler, SystemUiProxy.INSTANCE.get(this));
new SplitSelectStateController(SystemUiProxy.INSTANCE.get(this));
mDragLayer.recreateControllers();
mFallbackRecentsView.init(mActionsView, controller);
}
@@ -90,7 +90,8 @@ public abstract class SwipeUpAnimationLogic implements
mGestureState = gestureState;
mIsSwipeForStagedSplit = ENABLE_SPLIT_SELECT.get() &&
LauncherSplitScreenListener.INSTANCE.getNoCreate().getSplitTaskIds().length > 1;
LauncherSplitScreenListener.INSTANCE.getNoCreate()
.getRunningSplitTaskIds().length > 1;
TaskViewSimulator primaryTVS = new TaskViewSimulator(context,
gestureState.getActivityInterface());
@@ -11,20 +11,54 @@ import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
import com.android.launcher3.util.SplitConfigurationOptions.StageType;
import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitTaskPosition;
import com.android.quickstep.SystemUiProxy;
import com.android.systemui.shared.system.TaskStackChangeListener;
import com.android.systemui.shared.system.TaskStackChangeListeners;
import com.android.wm.shell.splitscreen.ISplitScreenListener;
/**
* Listeners for system wide split screen position and stage changes.
* Use {@link #getSplitTaskIds()} to determine which tasks, if any, are in staged split.
*
* Use {@link #getRunningSplitTaskIds()} to determine which tasks, if any, are actively in
* staged split.
*
* Use {@link #getPersistentSplitIds()} to know if tasks were in split screen before a quickswitch
* gesture happened.
*/
public class LauncherSplitScreenListener extends ISplitScreenListener.Stub {
public static final MainThreadInitializedObject<LauncherSplitScreenListener> INSTANCE =
new MainThreadInitializedObject<>(LauncherSplitScreenListener::new);
private static final int[] EMPTY_ARRAY = {};
private final StagedSplitTaskPosition mMainStagePosition = new StagedSplitTaskPosition();
private final StagedSplitTaskPosition mSideStagePosition = new StagedSplitTaskPosition();
private boolean mIsRecentsListFrozen = false;
private final TaskStackChangeListener mTaskStackListener = new TaskStackChangeListener() {
@Override
public void onRecentTaskListFrozenChanged(boolean frozen) {
super.onRecentTaskListFrozenChanged(frozen);
mIsRecentsListFrozen = frozen;
if (frozen) {
mPersistentGroupedIds = getRunningSplitTaskIds();
} else {
// TODO(b/198310766) Need to also explicitly exit split screen if
// we're not currently viewing split screened apps
mPersistentGroupedIds = EMPTY_ARRAY;
}
}
};
/**
* Gets set to current split taskIDs whenever the task list is frozen, and set to empty array
* whenever task list unfreezes.
* When not null, this indicates that we need to load a GroupedTaskView as the most recent
* page, so user can quickswitch back to a grouped task.
*/
private int[] mPersistentGroupedIds;
public LauncherSplitScreenListener(Context context) {
mMainStagePosition.stageType = SplitConfigurationOptions.STAGE_TYPE_MAIN;
mSideStagePosition.stageType = SplitConfigurationOptions.STAGE_TYPE_SIDE;
@@ -33,17 +67,30 @@ public class LauncherSplitScreenListener extends ISplitScreenListener.Stub {
/** Also call {@link #destroy()} when done. */
public void init() {
SystemUiProxy.INSTANCE.getNoCreate().registerSplitScreenListener(this);
TaskStackChangeListeners.getInstance().registerTaskStackListener(mTaskStackListener);
}
public void destroy() {
SystemUiProxy.INSTANCE.getNoCreate().unregisterSplitScreenListener(this);
TaskStackChangeListeners.getInstance().unregisterTaskStackListener(mTaskStackListener);
}
/**
* This method returns the active split taskIDs that were active if a user quickswitched from
* split screen to a fullscreen app as long as the recents task list remains frozen.
*/
public int[] getPersistentSplitIds() {
if (mIsRecentsListFrozen) {
return mPersistentGroupedIds;
} else {
return getRunningSplitTaskIds();
}
}
/**
* @return index 0 will be task in left/top position, index 1 in right/bottom position.
* Will return empty array if device is not in staged split
*/
public int[] getSplitTaskIds() {
public int[] getRunningSplitTaskIds() {
if (mMainStagePosition.taskId == -1 || mSideStagePosition.taskId == -1) {
return new int[]{};
}
@@ -22,7 +22,6 @@ import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITIO
import android.app.ActivityThread;
import android.graphics.Rect;
import android.os.Handler;
import android.os.IBinder;
import android.view.RemoteAnimationAdapter;
import android.view.SurfaceControl;
@@ -40,6 +39,8 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.RemoteTransitionCompat;
import com.android.systemui.shared.system.RemoteTransitionRunner;
import java.util.function.Consumer;
/**
* Represent data needed for the transient state when user has selected one app for split screen
* and is in the process of either a) selecting a second app or b) exiting intention to invoke split
@@ -52,7 +53,7 @@ public class SplitSelectStateController {
private Task mSecondTask;
private Rect mInitialBounds;
public SplitSelectStateController(Handler handler, SystemUiProxy systemUiProxy) {
public SplitSelectStateController(SystemUiProxy systemUiProxy) {
mSystemUiProxy = systemUiProxy;
}
@@ -71,13 +72,14 @@ public class SplitSelectStateController {
*/
public void setSecondTaskId(Task taskView) {
mSecondTask = taskView;
launchTasks(mInitialTask, mSecondTask, mStagePosition);
launchTasks(mInitialTask, mSecondTask, mStagePosition, null /*callback*/);
}
/**
* @param stagePosition representing location of task1
*/
public void launchTasks(Task task1, Task task2, @StagePosition int stagePosition) {
public void launchTasks(Task task1, Task task2, @StagePosition int stagePosition,
Consumer<Boolean> callback) {
// Assume initial task is for top/left part of screen
final int[] taskIds = stagePosition == STAGE_POSITION_TOP_OR_LEFT
? new int[]{task1.key.id, task2.key.id}
@@ -90,7 +92,7 @@ public class SplitSelectStateController {
new RemoteTransitionCompat(animationRunner, MAIN_EXECUTOR));
} else {
RemoteSplitLaunchAnimationRunner animationRunner =
new RemoteSplitLaunchAnimationRunner(task1, task2);
new RemoteSplitLaunchAnimationRunner(task1, task2, callback);
final RemoteAnimationAdapter adapter = new RemoteAnimationAdapter(
RemoteAnimationAdapterCompat.wrapRemoteAnimationRunner(animationRunner),
300, 150,
@@ -136,10 +138,13 @@ public class SplitSelectStateController {
private final Task mInitialTask;
private final Task mSecondTask;
private final Consumer<Boolean> mSuccessCallback;
RemoteSplitLaunchAnimationRunner(Task initialTask, Task secondTask) {
RemoteSplitLaunchAnimationRunner(Task initialTask, Task secondTask,
Consumer<Boolean> successCallback) {
mInitialTask = initialTask;
mSecondTask = secondTask;
mSuccessCallback = successCallback;
}
@Override
@@ -147,13 +152,21 @@ public class SplitSelectStateController {
RemoteAnimationTargetCompat[] wallpapers, RemoteAnimationTargetCompat[] nonApps,
Runnable finishedCallback) {
TaskViewUtils.composeRecentsSplitLaunchAnimatorLegacy(mInitialTask,
mSecondTask, apps, wallpapers, nonApps, finishedCallback);
mSecondTask, apps, wallpapers, nonApps, () -> {
finishedCallback.run();
if (mSuccessCallback != null) {
mSuccessCallback.accept(true);
}
});
// After successful launch, call resetState
resetState();
}
@Override
public void onAnimationCancelled() {
if (mSuccessCallback != null) {
mSuccessCallback.accept(false);
}
resetState();
}
}
@@ -3,6 +3,8 @@ package com.android.quickstep.views;
import android.content.Context;
import android.util.AttributeSet;
import androidx.annotation.NonNull;
import com.android.launcher3.R;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.util.SplitConfigurationOptions;
@@ -12,6 +14,8 @@ import com.android.quickstep.util.CancellableTask;
import com.android.quickstep.util.RecentsOrientedState;
import com.android.systemui.shared.recents.model.Task;
import java.util.function.Consumer;
/**
* TaskView that contains and shows thumbnails for not one, BUT TWO(!!) tasks
*
@@ -98,10 +102,16 @@ public class GroupedTaskView extends TaskView {
@Override
public RunnableList launchTaskAnimated() {
getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask,
SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT);
SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT, null /*callback*/);
return null;
}
@Override
public void launchTask(@NonNull Consumer<Boolean> callback, boolean freezeTaskList) {
getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask,
SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT, callback);
}
@Override
public void onRecycle() {
super.onRecycle();
@@ -1259,7 +1259,7 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
mIgnoreResetTaskId == -1 ? null : getTaskViewByTaskId(mIgnoreResetTaskId);
int[] splitTaskIds =
LauncherSplitScreenListener.INSTANCE.getNoCreate().getSplitTaskIds();
LauncherSplitScreenListener.INSTANCE.getNoCreate().getPersistentSplitIds();
int requiredGroupTaskViews = splitTaskIds.length / 2;
// Subtract half the number of split tasks and not total number because we've already
@@ -1963,6 +1963,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
/**
* Called only when a swipe-up gesture from an app has completed. Only called after
* {@link #onGestureAnimationStart} and {@link #onGestureAnimationEnd()}.
*
* TODO(b/198310766) Need to also explicitly exit split screen if
* the swipe up was to home
*/
public void onSwipeUpAnimationSuccess() {
animateUpTaskIconScale();