From 153cd69d14095e046b37b52bffc0fe18748bd90f Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Tue, 4 Jan 2022 21:40:20 -0800 Subject: [PATCH 1/3] Apply scrim protection to atomic state transition ALLAPPS -> NORMAL Bug: 209480401 Test: manual, video attached on the bug TL;DR;; minimized the delta for sc-v2 Change-Id: If8c9281bb4366540b9a4ea10a9b363ce82d78daf --- .../states/QuickstepAtomicAnimationFactory.java | 13 +++++++++++++ .../PortraitStatesTouchController.java | 8 ++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java index 0e2fbbc2bf..75cf5cb3a5 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java @@ -17,6 +17,7 @@ package com.android.launcher3.uioverrides.states; import static android.view.View.VISIBLE; +import static com.android.launcher3.LauncherState.ALL_APPS; import static com.android.launcher3.LauncherState.HINT_STATE; import static com.android.launcher3.LauncherState.HINT_STATE_TWO_BUTTON; import static com.android.launcher3.LauncherState.NORMAL; @@ -44,6 +45,10 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_FADE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_SCALE; import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE; +import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD; +import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD; +import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_SCRIM_OPAQUE_THRESHOLD; +import static com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController.ALL_APPS_SCRIM_VISIBLE_THRESHOLD; import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; import android.animation.ValueAnimator; @@ -52,6 +57,7 @@ import com.android.launcher3.CellLayout; import com.android.launcher3.Hotseat; import com.android.launcher3.LauncherState; import com.android.launcher3.Workspace; +import com.android.launcher3.anim.Interpolators; import com.android.launcher3.states.StateAnimationConfig; import com.android.launcher3.uioverrides.QuickstepLauncher; import com.android.quickstep.SysUINavigationMode; @@ -171,6 +177,13 @@ public class QuickstepAtomicAnimationFactory extends mHintToNormalDuration = (int) va.getDuration(); } config.duration = Math.max(config.duration, mHintToNormalDuration); + } else if (fromState == ALL_APPS && toState == NORMAL) { + config.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL, + 1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD, + 1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD)); + config.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(DEACCEL, + 1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD, + 1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD)); } } } diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java index 3c83d25b71..59ade49761 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java @@ -52,22 +52,22 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr /** * The progress at which all apps content will be fully visible. */ - protected static final float ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD = 0.8f; + public static final float ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD = 0.8f; /** * Minimum clamping progress for fading in all apps content */ - protected static final float ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD = 0.5f; + public static final float ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD = 0.5f; /** * Minimum clamping progress for fading in all apps scrim */ - protected static final float ALL_APPS_SCRIM_VISIBLE_THRESHOLD = .1f; + public static final float ALL_APPS_SCRIM_VISIBLE_THRESHOLD = .1f; /** * Maximum clamping progress for opaque all apps scrim */ - protected static final float ALL_APPS_SCRIM_OPAQUE_THRESHOLD = .5f; + public static final float ALL_APPS_SCRIM_OPAQUE_THRESHOLD = .5f; private final PortraitOverviewStateTouchHelper mOverviewPortraitStateTouchHelper; From 1465a5af7bfd7ba881587e772431989d0e824f5f Mon Sep 17 00:00:00 2001 From: Vinit Nayak Date: Wed, 22 Dec 2021 14:44:36 -0800 Subject: [PATCH 2/3] Handle split selection when animation is disabled * Consolidate setState() and setStateWithAnimation() to be handled in the same manner * If no animation, we run the created PendingAnimation right away Fixes: 209935590 Test: Tested w/ and w/o animation Change-Id: I1d6fdba21761b6721e6bd52234016178547cd437 --- .../BaseRecentsViewStateController.java | 13 ---- .../RecentsViewStateController.java | 70 ++++++++++++++----- .../quickstep/TaskShortcutFactory.java | 1 + .../util/SplitSelectStateController.java | 7 -- .../android/quickstep/views/RecentsView.java | 2 +- 5 files changed, 54 insertions(+), 39 deletions(-) diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java index c85b2566a7..0eaea83801 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java @@ -29,12 +29,9 @@ import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW; import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET; import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS; import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY; -import static com.android.quickstep.views.RecentsView.TASK_PRIMARY_SPLIT_TRANSLATION; -import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_SPLIT_TRANSLATION; import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION; import android.util.FloatProperty; -import android.util.Pair; import androidx.annotation.NonNull; @@ -43,7 +40,6 @@ import com.android.launcher3.LauncherState; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.statemanager.StateManager.StateHandler; import com.android.launcher3.states.StateAnimationConfig; -import com.android.launcher3.touch.PagedOrientationHandler; import com.android.quickstep.views.RecentsView; /** @@ -100,15 +96,6 @@ public abstract class BaseRecentsViewStateController config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR)); setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f, config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR)); - PagedOrientationHandler orientationHandler = - ((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler(); - Pair taskViewsFloat = - orientationHandler.getSplitSelectTaskOffset( - TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION, - mLauncher.getDeviceProfile()); - setter.setFloat(mRecentsView, taskViewsFloat.first, - toState.getSplitSelectTranslation(mLauncher), LINEAR); - setter.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR); setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0, config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT)); diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java index 19897a1bf8..32ce1c40d7 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java @@ -23,13 +23,17 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_AC import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA; import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS; import static com.android.quickstep.views.RecentsView.TASK_MODALNESS; +import static com.android.quickstep.views.RecentsView.TASK_PRIMARY_SPLIT_TRANSLATION; +import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_SPLIT_TRANSLATION; import static com.android.quickstep.views.TaskView.FLAG_UPDATE_ALL; import android.annotation.TargetApi; import android.os.Build; import android.util.FloatProperty; +import android.util.Pair; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.LauncherState; @@ -37,6 +41,7 @@ import com.android.launcher3.anim.AnimatorListeners; import com.android.launcher3.anim.PendingAnimation; import com.android.launcher3.anim.PropertySetter; import com.android.launcher3.states.StateAnimationConfig; +import com.android.launcher3.touch.PagedOrientationHandler; import com.android.launcher3.util.MultiValueAlpha; import com.android.quickstep.views.ClearAllButton; import com.android.quickstep.views.LauncherRecentsView; @@ -67,11 +72,7 @@ public final class RecentsViewStateController extends // DepthController to prevent optimizations which might occlude the layers behind mLauncher.getDepthController().setHasContentBehindLauncher(state.overviewUi); - if (isSplitSelectionState(state)) { - mRecentsView.applySplitPrimaryScrollOffset(); - } else { - mRecentsView.resetSplitPrimaryScrollOffset(); - } + handleSplitSelectionState(state, null); } @Override @@ -92,16 +93,7 @@ public final class RecentsViewStateController extends builder.addListener(AnimatorListeners.forSuccessCallback(() -> mLauncher.getDepthController().setHasContentBehindLauncher(toState.overviewUi))); - // Create or dismiss split screen select animations - LauncherState currentState = mLauncher.getStateManager().getState(); - if (isSplitSelectionState(toState) && !isSplitSelectionState(currentState)) { - builder.add(mRecentsView.createSplitSelectInitAnimation().buildAnim()); - } - if (isSplitSelectionState(toState)) { - mRecentsView.applySplitPrimaryScrollOffset(); - } else { - mRecentsView.resetSplitPrimaryScrollOffset(); - } + handleSplitSelectionState(toState, builder); setAlphas(builder, config, toState); builder.setFloat(mRecentsView, FULLSCREEN_PROGRESS, @@ -109,10 +101,52 @@ public final class RecentsViewStateController extends } /** - * @return true if {@param toState} is {@link LauncherState#OVERVIEW_SPLIT_SELECT} + * Create or dismiss split screen select animations. + * @param builder if null then this will run the split select animations right away, otherwise + * will add animations to builder. */ - private boolean isSplitSelectionState(@NonNull LauncherState toState) { - return toState == OVERVIEW_SPLIT_SELECT; + private void handleSplitSelectionState(@NonNull LauncherState toState, + @Nullable PendingAnimation builder) { + LauncherState currentState = mLauncher.getStateManager().getState(); + boolean animate = builder != null; + PagedOrientationHandler orientationHandler = + ((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler(); + Pair taskViewsFloat = + orientationHandler.getSplitSelectTaskOffset( + TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION, + mLauncher.getDeviceProfile()); + + if (isSplitSelectionState(currentState, toState)) { + // Animation to "dismiss" selected taskView + PendingAnimation splitSelectInitAnimation = + mRecentsView.createSplitSelectInitAnimation(); + // Add properties to shift remaining taskViews to get out of placeholder view + splitSelectInitAnimation.setFloat(mRecentsView, taskViewsFloat.first, + toState.getSplitSelectTranslation(mLauncher), LINEAR); + splitSelectInitAnimation.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR); + + if (!animate && isSplitSelectionState(currentState, toState)) { + splitSelectInitAnimation.buildAnim().start(); + } else if (animate && + isSplitSelectionState(currentState, toState)) { + builder.add(splitSelectInitAnimation.buildAnim()); + } + } + + if (isSplitSelectionState(currentState, toState)) { + mRecentsView.applySplitPrimaryScrollOffset(); + } else { + mRecentsView.resetSplitPrimaryScrollOffset(); + } + } + + /** + * @return true if {@param toState} is {@link LauncherState#OVERVIEW_SPLIT_SELECT} + * and {@param fromState} is not {@link LauncherState#OVERVIEW_SPLIT_SELECT} + */ + private boolean isSplitSelectionState(@NonNull LauncherState fromState, + @NonNull LauncherState toState) { + return fromState != OVERVIEW_SPLIT_SELECT && toState == OVERVIEW_SPLIT_SELECT; } private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config, diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java index cbdbdb5571..f507ea3dfc 100644 --- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java +++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java @@ -242,6 +242,7 @@ public interface TaskShortcutFactory { } } + /** @Deprecated */ TaskShortcutFactory SPLIT_SCREEN = new MultiWindowFactory(R.drawable.ic_split_screen, R.string.recent_task_option_split_screen, LAUNCHER_SYSTEM_SHORTCUT_SPLIT_SCREEN_TAP) { diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java index d3108936e7..5253e8c657 100644 --- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java +++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java @@ -64,7 +64,6 @@ public class SplitSelectStateController { private @StagePosition int mStagePosition; private Task mInitialTask; private Task mSecondTask; - private Rect mInitialBounds; private boolean mRecentsAnimationRunning; /** If not null, this is the TaskView we want to launch from */ @Nullable @@ -86,7 +85,6 @@ public class SplitSelectStateController { Rect initialBounds) { mInitialTask = task; mStagePosition = stagePosition; - mInitialBounds = initialBounds; } /** @@ -229,7 +227,6 @@ public class SplitSelectStateController { mInitialTask = null; mSecondTask = null; mStagePosition = SplitConfigurationOptions.STAGE_POSITION_UNDEFINED; - mInitialBounds = null; mRecentsAnimationRunning = false; mLaunchingTaskView = null; } @@ -241,8 +238,4 @@ public class SplitSelectStateController { public boolean isSplitSelectActive() { return mInitialTask != null && mSecondTask == null; } - - public Rect getInitialBounds() { - return mInitialBounds; - } } diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 10efa3ecbf..f0e57c9932 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -3994,7 +3994,7 @@ public abstract class RecentsView Date: Wed, 5 Jan 2022 14:43:43 -0800 Subject: [PATCH 3/3] Use list instead of array when filtering non-app leashes * Non-apps leashes can contain non-divider targets, which was creating null elements in the array when an index didn't get assigned. * With a list we don't have to worry about empty index gaps * Also remove the animation for the divider for certain gestures because the surface isn't always valid for the full duration of the animation. We probably would need to synchronize with rest of recents animation Fixes: 212218930 Test: No longer crashes when swipe up, hold, then swipe down Change-Id: Ia1fc4d66e73f21b55fdbfe59342af025e2a525d9 --- quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java | 4 ++-- quickstep/src/com/android/quickstep/TaskViewUtils.java | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java index c7f1edd292..9f1e47f15a 100644 --- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java @@ -1001,7 +1001,7 @@ public abstract class AbsSwipeUpHandler, } if (mRecentsAnimationTargets != null) { TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, - true /*shown*/, true /*animate*/); + true /*shown*/, false /*animate*/); } break; } @@ -1654,7 +1654,7 @@ public abstract class AbsSwipeUpHandler, if (mRecentsAnimationTargets != null) { TaskViewUtils.setSplitAuxiliarySurfacesShown(mRecentsAnimationTargets.nonApps, - true /*shown*/, true /*animate*/); + true /*shown*/, false /*animate*/); } // Leave the pending invisible flag, as it may be used by wallpaper open animation. diff --git a/quickstep/src/com/android/quickstep/TaskViewUtils.java b/quickstep/src/com/android/quickstep/TaskViewUtils.java index 14f3ec453c..5d9a537165 100644 --- a/quickstep/src/com/android/quickstep/TaskViewUtils.java +++ b/quickstep/src/com/android/quickstep/TaskViewUtils.java @@ -84,6 +84,7 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat; import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams; import java.util.ArrayList; +import java.util.List; /** * Utility class for helpful methods related to {@link TaskView} objects and their tasks. @@ -606,13 +607,13 @@ public final class TaskViewUtils { } SurfaceControl.Transaction t = new SurfaceControl.Transaction(); - SurfaceControl[] auxiliarySurfaces = new SurfaceControl[nonApps.length]; + List auxiliarySurfaces = new ArrayList<>(nonApps.length); boolean hasSurfaceToAnimate = false; for (int i = 0; i < nonApps.length; ++i) { final RemoteAnimationTargetCompat targ = nonApps[i]; final SurfaceControl leash = targ.leash.getSurfaceControl(); if (targ.windowType == TYPE_DOCK_DIVIDER && leash != null) { - auxiliarySurfaces[i] = leash; + auxiliarySurfaces.add(leash); hasSurfaceToAnimate = true; } }