Merge "Allow starting split from home, selecting second app from overview" into udc-qpr-dev

This commit is contained in:
Vinit Nayak
2023-06-21 18:24:09 +00:00
committed by Android (Google) Code Review
7 changed files with 122 additions and 19 deletions

View File

@@ -46,6 +46,7 @@ import androidx.annotation.NonNull;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
@@ -113,7 +114,9 @@ public abstract class BaseRecentsViewStateController<T extends RecentsView>
setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f,
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
if (mRecentsView.isSplitSelectionActive()) {
boolean exitingOverview = !FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()
|| !toState.overviewUi;
if (mRecentsView.isSplitSelectionActive() && exitingOverview) {
// TODO (b/238651489): Refactor state management to avoid need for double check
FloatingTaskView floatingTask = mRecentsView.getFirstFloatingTaskView();
if (floatingTask != null) {

View File

@@ -615,9 +615,10 @@ public class QuickstepLauncher extends Launcher {
mSplitSelectStateController.findLastActiveTaskAndRunCallback(
splitSelectSource.itemInfo.getComponentKey(),
foundTask -> {
splitSelectSource.alreadyRunningTaskId = foundTask == null
? INVALID_TASK_ID
: foundTask.key.id;
boolean taskWasFound = foundTask != null;
splitSelectSource.alreadyRunningTaskId = taskWasFound
? foundTask.key.id
: INVALID_TASK_ID;
if (ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
startSplitToHome(splitSelectSource);
} else {
@@ -1295,7 +1296,7 @@ public class QuickstepLauncher extends Launcher {
groupTask.task1.key.id,
groupTask.task2.key.id,
SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT,
/* callback= */ success -> {},
/* callback= */ success -> mSplitSelectStateController.resetState(),
/* freezeTaskList= */ true,
groupTask.mSplitBounds == null
? DEFAULT_SPLIT_RATIO

View File

@@ -0,0 +1,17 @@
package com.android.quickstep
interface SplitSelectionListener {
/** Called when the first app has been selected with the intention to launch split screen */
fun onSplitSelectionActive()
/** Called when the second app has been selected with the intention to launch split screen */
fun onSplitSelectionConfirmed()
/**
* Called when the user no longer is in the process of selecting apps for split screen.
* [launchedSplit] will be true if selected apps have launched successfully (either in
* split screen or fullscreen), false if the user canceled/exited the selection process
*/
fun onSplitSelectionExit(launchedSplit: Boolean) {
}
}

View File

@@ -35,6 +35,7 @@ import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.statemanager.StateManager.StateListener;
import com.android.launcher3.util.SplitConfigurationOptions;
@@ -246,7 +247,11 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity, RecentsSta
setOverviewSelectEnabled(false);
}
if (finalState != OVERVIEW_SPLIT_SELECT) {
resetFromSplitSelectionState();
if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
mSplitSelectStateController.resetState();
} else {
resetFromSplitSelectionState();
}
}
if (isOverlayEnabled) {

View File

@@ -73,16 +73,18 @@ import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.util.SplitConfigurationOptions;
import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.SplitSelectionListener;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskAnimationManager;
import com.android.quickstep.TaskViewUtils;
import com.android.quickstep.views.FloatingTaskView;
import com.android.quickstep.views.GroupedTaskView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.Task;
import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
@@ -138,6 +140,8 @@ public class SplitSelectStateController {
private FloatingTaskView mFirstFloatingTaskView;
private final List<SplitSelectionListener> mSplitSelectionListeners = new ArrayList<>();
public SplitSelectStateController(Context context, Handler handler, StateManager stateManager,
DepthController depthController, StatsLogManager statsLogManager,
SystemUiProxy systemUiProxy, RecentsModel recentsModel) {
@@ -247,6 +251,27 @@ public class SplitSelectStateController {
&& task.key.userId == componentKey.user.getIdentifier();
}
/**
* Listener will only get callbacks going forward from the point of registration. No
* methods will be fired upon registering.
*/
public void registerSplitListener(@NonNull SplitSelectionListener listener) {
if (mSplitSelectionListeners.contains(listener)) {
return;
}
mSplitSelectionListeners.add(listener);
}
public void unregisterSplitListener(@NonNull SplitSelectionListener listener) {
mSplitSelectionListeners.remove(listener);
}
private void dispatchOnSplitSelectionExit() {
for (SplitSelectionListener listener : mSplitSelectionListeners) {
listener.onSplitSelectionExit(false);
}
}
/**
* To be called when the actual tasks ({@link #mInitialTaskId}, {@link #mSecondTaskId}) are
* to be launched. Call after launcher side animations are complete.
@@ -790,12 +815,16 @@ public class SplitSelectStateController {
}
/**
* To be called if split select was cancelled
* To be called whenever we exit split selection state. If
* {@link FeatureFlags#ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE} is set, this should be the
* central way split is getting reset, which should then go through the callbacks to reset
* other state.
*/
public void resetState() {
if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
mSplitSelectDataHolder.resetState();
}
dispatchOnSplitSelectionExit();
mInitialTaskId = INVALID_TASK_ID;
mInitialTaskIntent = null;
mSecondTaskId = INVALID_TASK_ID;

View File

@@ -37,6 +37,7 @@ import androidx.annotation.Nullable;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.LauncherState;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.statehandlers.DepthController;
import com.android.launcher3.statehandlers.DesktopVisibilityController;
@@ -218,7 +219,11 @@ public class LauncherRecentsView extends RecentsView<QuickstepLauncher, Launcher
@Override
protected boolean canLaunchFullscreenTask() {
return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
return !mSplitSelectStateController.isSplitSelectActive();
} else {
return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
}
}
@Override

View File

@@ -173,6 +173,7 @@ import com.android.quickstep.RemoteAnimationTargets;
import com.android.quickstep.RemoteTargetGluer;
import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
import com.android.quickstep.RotationTouchHelper;
import com.android.quickstep.SplitSelectionListener;
import com.android.quickstep.SystemUiProxy;
import com.android.quickstep.TaskOverlayFactory;
import com.android.quickstep.TaskThumbnailCache;
@@ -662,7 +663,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
/**
* Placeholder view indicating where the first split screen selected app will be placed
*/
private SplitSelectStateController mSplitSelectStateController;
protected SplitSelectStateController mSplitSelectStateController;
/**
* The first task that split screen selection was initiated with. When split select state is
* initialized, we create a
@@ -685,6 +687,19 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
@Nullable
private SplitSelectSource mSplitSelectSource;
private final SplitSelectionListener mSplitSelectionListener = new SplitSelectionListener() {
@Override
public void onSplitSelectionConfirmed() { }
@Override
public void onSplitSelectionActive() { }
@Override
public void onSplitSelectionExit(boolean launchedSplit) {
resetFromSplitSelectionState();
}
};
/**
* Keeps track of the index of the TaskView that split screen was initialized with so we know
* where to insert it back into list of taskViews in case user backs out of entering split
@@ -1065,6 +1080,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
mIPipAnimationListener);
mOrientationState.initListeners();
mTaskOverlayFactory.initListeners();
if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
mSplitSelectStateController.registerSplitListener(mSplitSelectionListener);
}
}
@Override
@@ -1083,6 +1101,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
mIPipAnimationListener.setActivityAndRecentsView(null, null);
mOrientationState.destroyListeners();
mTaskOverlayFactory.removeListeners();
if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
mSplitSelectStateController.unregisterSplitListener(mSplitSelectionListener);
}
}
@Override
@@ -1660,8 +1681,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
// If we are entering Overview as a result of initiating a split from somewhere else
// (e.g. split from Home), we need to make sure the staged app is not drawn as a thumbnail.
int stagedTaskIdToBeRemovedFromGrid;
if (mSplitSelectSource != null) {
stagedTaskIdToBeRemovedFromGrid = mSplitSelectSource.alreadyRunningTaskId;
if (isSplitSelectionActive()) {
stagedTaskIdToBeRemovedFromGrid = mSplitSelectStateController.getInitialTaskId();
updateCurrentTaskActionsVisibility();
} else {
stagedTaskIdToBeRemovedFromGrid = INVALID_TASK_ID;
@@ -2367,7 +2388,9 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
remoteTargetHandle.getTransformParams().setTargetSet(null);
remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(false);
});
resetFromSplitSelectionState();
if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
resetFromSplitSelectionState();
}
// These are relatively expensive and don't need to be done this frame (RecentsView isn't
// visible anyway), so defer by a frame to get off the critical path, e.g. app to home.
@@ -3251,7 +3274,11 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
} else {
// If transition to split select was interrupted, clean up to prevent glitches
resetFromSplitSelectionState();
if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
mSplitSelectStateController.resetState();
} else {
resetFromSplitSelectionState();
}
InteractionJankMonitorWrapper.cancel(
InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
}
@@ -3284,8 +3311,13 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
true /* isStagedTask */);
pendingAnimation.addEndListener(animationSuccess ->
mSplitSelectStateController.launchInitialAppFullscreen(launchSuccess ->
resetFromSplitSelectionState()));
mSplitSelectStateController.launchInitialAppFullscreen(launchSuccess -> {
if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
mSplitSelectStateController.resetState();
} else {
resetFromSplitSelectionState();
}
}));
pendingAnimation.buildAnim().start();
}
@@ -4737,7 +4769,13 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
pendingAnimation.addEndListener(aBoolean -> {
mSplitSelectStateController.launchSplitTasks(
aBoolean1 -> RecentsView.this.resetFromSplitSelectionState());
aBoolean1 -> {
if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
mSplitSelectStateController.resetState();
} else {
resetFromSplitSelectionState();
}
});
InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
});
@@ -4759,7 +4797,8 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
@SuppressLint("WrongCall")
protected void resetFromSplitSelectionState() {
if (mSplitSelectSource != null || mSplitHiddenTaskViewIndex != -1) {
if (mSplitSelectSource != null || mSplitHiddenTaskViewIndex != -1 ||
FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
safeRemoveDragLayerView(mSplitSelectStateController.getFirstFloatingTaskView());
safeRemoveDragLayerView(mSecondFloatingTaskView);
safeRemoveDragLayerView(mSplitInstructionsView);
@@ -4778,7 +4817,11 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
setTaskViewsPrimarySplitTranslation(0);
setTaskViewsSecondarySplitTranslation(0);
mSplitSelectStateController.resetState();
if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
// When flag is on, this method gets called from resetState() call below, let's avoid
// infinite recursion today
mSplitSelectStateController.resetState();
}
if (mSplitHiddenTaskViewIndex == -1) {
return;
}