From e70eda424b159e84427eeba3f528f2fffdb2fbfd Mon Sep 17 00:00:00 2001 From: Alex Chau Date: Thu, 2 Jan 2025 15:02:58 +0000 Subject: [PATCH] Combine RecentsViewStateController with base class - BaseRecentsViewStateController is only inherited by RecentsViewStateController, remove the base class to simplify code - Also converted RecentsViewStateController to Kotlin and remove a bunch of warnings Fix: 387267938 Test: presubmit and manual Flag: EXEMPT refactor Change-Id: I18e9c2b186a64a0af39230cb41e3b3f4949107d5 --- .../BaseRecentsViewStateController.java | 173 ---------- .../RecentsViewStateController.java | 188 ----------- .../uioverrides/RecentsViewStateController.kt | 316 ++++++++++++++++++ .../FallbackRecentsStateController.java | 2 +- .../android/quickstep/views/RecentsView.java | 52 +-- 5 files changed, 343 insertions(+), 388 deletions(-) delete mode 100644 quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java delete mode 100644 quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java create mode 100644 quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java deleted file mode 100644 index 721c831a42..0000000000 --- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2019 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.launcher3.uioverrides; - -import static com.android.app.animation.Interpolators.ACCELERATE_DECELERATE; -import static com.android.app.animation.Interpolators.AGGRESSIVE_EASE_IN_OUT; -import static com.android.app.animation.Interpolators.FINAL_FRAME; -import static com.android.app.animation.Interpolators.INSTANT; -import static com.android.app.animation.Interpolators.LINEAR; -import static com.android.launcher3.Flags.enableLargeDesktopWindowingTile; -import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME; -import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_HOME; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y; -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.DESKTOP_CAROUSEL_DETACH_PROGRESS; -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_SECONDARY_TRANSLATION; -import static com.android.quickstep.views.RecentsView.TASK_THUMBNAIL_SPLASH_ALPHA; - -import android.util.FloatProperty; -import android.view.animation.Interpolator; - -import androidx.annotation.NonNull; - -import com.android.launcher3.LauncherState; -import com.android.launcher3.anim.PendingAnimation; -import com.android.launcher3.config.FeatureFlags; -import com.android.launcher3.statemanager.StateManager.StateHandler; -import com.android.launcher3.states.StateAnimationConfig; -import com.android.quickstep.views.RecentsView; - -/** - * State handler for recents view. Manages UI changes and animations for recents view based off the - * current {@link LauncherState}. - * - * @param the recents view - */ -public abstract class BaseRecentsViewStateController - implements StateHandler { - protected final T mRecentsView; - protected final QuickstepLauncher mLauncher; - - public BaseRecentsViewStateController(@NonNull QuickstepLauncher launcher) { - mLauncher = launcher; - mRecentsView = launcher.getOverviewPanel(); - } - - @Override - public void setState(@NonNull LauncherState state) { - float[] scaleAndOffset = state.getOverviewScaleAndOffset(mLauncher); - RECENTS_SCALE_PROPERTY.set(mRecentsView, scaleAndOffset[0]); - ADJACENT_PAGE_HORIZONTAL_OFFSET.set(mRecentsView, scaleAndOffset[1]); - TASK_SECONDARY_TRANSLATION.set(mRecentsView, 0f); - - getContentAlphaProperty().set(mRecentsView, state.isRecentsViewVisible ? 1f : 0); - getTaskModalnessProperty().set(mRecentsView, state.getOverviewModalness()); - RECENTS_GRID_PROGRESS.set(mRecentsView, - state.displayOverviewTasksAsGrid(mLauncher.getDeviceProfile()) ? 1f : 0f); - TASK_THUMBNAIL_SPLASH_ALPHA.set(mRecentsView, state.showTaskThumbnailSplash() ? 1f : 0f); - if (enableLargeDesktopWindowingTile()) { - DESKTOP_CAROUSEL_DETACH_PROGRESS.set(mRecentsView, - state.detachDesktopCarousel() ? 1f : 0f); - } - } - - @Override - public void setStateWithAnimation(LauncherState toState, StateAnimationConfig config, - PendingAnimation builder) { - if (config.hasAnimationFlag(SKIP_OVERVIEW)) { - return; - } - setStateWithAnimationInternal(toState, config, builder); - builder.addEndListener(success -> { - if (!success && !toState.isRecentsViewVisible) { - mRecentsView.reset(); - } - }); - } - - /** - * Core logic for animating the recents view UI. - * - * @param toState state to animate to - * @param config current animation config - * @param setter animator set builder - */ - void setStateWithAnimationInternal(@NonNull final LauncherState toState, - @NonNull StateAnimationConfig config, @NonNull PendingAnimation setter) { - float[] scaleAndOffset = toState.getOverviewScaleAndOffset(mLauncher); - setter.setFloat(mRecentsView, RECENTS_SCALE_PROPERTY, scaleAndOffset[0], - config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR)); - setter.setFloat(mRecentsView, ADJACENT_PAGE_HORIZONTAL_OFFSET, scaleAndOffset[1], - config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR)); - setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f, - config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR)); - - boolean exitingOverview = - !FeatureFlags.enableSplitContextually() && !toState.isRecentsViewVisible; - if (mRecentsView.isSplitSelectionActive() && exitingOverview) { - setter.add(mRecentsView.getSplitSelectController().getSplitAnimationController() - .createPlaceholderDismissAnim(mLauncher, LAUNCHER_SPLIT_SELECTION_EXIT_HOME, - setter.getDuration())); - setter.setViewAlpha( - mRecentsView.getSplitInstructionsView(), - 0, - config.getInterpolator( - ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE, - LINEAR - ) - ); - } - - setter.setFloat(mRecentsView, getContentAlphaProperty(), - toState.isRecentsViewVisible ? 1 : 0, - config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT)); - - setter.setFloat( - mRecentsView, getTaskModalnessProperty(), - toState.getOverviewModalness(), - config.getInterpolator(ANIM_OVERVIEW_MODAL, LINEAR)); - - LauncherState fromState = mLauncher.getStateManager().getState(); - setter.setFloat(mRecentsView, TASK_THUMBNAIL_SPLASH_ALPHA, - toState.showTaskThumbnailSplash() ? 1f : 0f, - getOverviewInterpolator(fromState, toState)); - - setter.setFloat(mRecentsView, RECENTS_GRID_PROGRESS, - toState.displayOverviewTasksAsGrid(mLauncher.getDeviceProfile()) ? 1f : 0f, - getOverviewInterpolator(fromState, toState)); - - if (enableLargeDesktopWindowingTile()) { - setter.setFloat(mRecentsView, DESKTOP_CAROUSEL_DETACH_PROGRESS, - toState.detachDesktopCarousel() ? 1f : 0f, - getOverviewInterpolator(fromState, toState)); - } - } - - private Interpolator getOverviewInterpolator(LauncherState fromState, LauncherState toState) { - return fromState == QUICK_SWITCH_FROM_HOME - ? ACCELERATE_DECELERATE - : toState.isRecentsViewVisible ? INSTANT : FINAL_FRAME; - } - - abstract FloatProperty getTaskModalnessProperty(); - - /** - * Get property for content alpha for the recents view. - * - * @return the float property for the view's content alpha - */ - abstract FloatProperty getContentAlphaProperty(); -} diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java deleted file mode 100644 index 111069ffc4..0000000000 --- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright (C) 2017 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.android.launcher3.uioverrides; - -import static com.android.app.animation.Interpolators.LINEAR; -import static com.android.launcher3.LauncherState.CLEAR_ALL_BUTTON; -import static com.android.launcher3.LauncherState.OVERVIEW; -import static com.android.launcher3.LauncherState.OVERVIEW_ACTIONS; -import static com.android.launcher3.LauncherState.OVERVIEW_SPLIT_SELECT; -import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE; -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 static com.android.wm.shell.Flags.enableSplitContextual; - -import android.animation.AnimatorSet; -import android.annotation.TargetApi; -import android.os.Build; -import android.util.FloatProperty; -import android.util.Log; -import android.util.Pair; - -import androidx.annotation.NonNull; - -import com.android.launcher3.LauncherState; -import com.android.launcher3.Utilities; -import com.android.launcher3.anim.AnimatedFloat; -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.quickstep.orientation.RecentsPagedOrientationHandler; -import com.android.quickstep.util.AnimUtils; -import com.android.quickstep.util.SplitAnimationTimings; -import com.android.quickstep.views.ClearAllButton; -import com.android.quickstep.views.LauncherRecentsView; -import com.android.quickstep.views.RecentsView; - -/** - * State handler for handling UI changes for {@link LauncherRecentsView}. In addition to managing - * the basic view properties, this class also manages changes in the task visuals. - */ -@TargetApi(Build.VERSION_CODES.O) -public final class RecentsViewStateController extends - BaseRecentsViewStateController { - - public RecentsViewStateController(QuickstepLauncher launcher) { - super(launcher); - } - - @Override - public void setState(@NonNull LauncherState state) { - super.setState(state); - if (state.isRecentsViewVisible) { - mRecentsView.updateEmptyMessage(); - } else { - mRecentsView.resetTaskVisuals(); - } - setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, new StateAnimationConfig(), state); - mRecentsView.setFullscreenProgress(state.getOverviewFullscreenProgress()); - // In Overview, we may be layering app surfaces behind Launcher, so we need to notify - // DepthController to prevent optimizations which might occlude the layers behind - mLauncher.getDepthController().setHasContentBehindLauncher(state.isRecentsViewVisible); - - PendingAnimation builder = - new PendingAnimation(state.getTransitionDuration(mLauncher, true)); - - handleSplitSelectionState(state, builder, /* animate */false); - } - - @Override - void setStateWithAnimationInternal(@NonNull LauncherState toState, - @NonNull StateAnimationConfig config, @NonNull PendingAnimation builder) { - super.setStateWithAnimationInternal(toState, config, builder); - - if (toState.isRecentsViewVisible) { - // While animating into recents, update the visible task data as needed - builder.addOnFrameCallback(() -> mRecentsView.loadVisibleTaskData(FLAG_UPDATE_ALL)); - mRecentsView.updateEmptyMessage(); - // TODO(b/246283207): Remove logging once root cause of flake detected. - if (Utilities.isRunningInTestHarness()) { - Log.d("b/246283207", "RecentsView#setStateWithAnimationInternal getCurrentPage(): " - + mRecentsView.getCurrentPage() - + ", getScrollForPage(getCurrentPage())): " - + mRecentsView.getScrollForPage(mRecentsView.getCurrentPage())); - } - } else { - builder.addListener( - AnimatorListeners.forSuccessCallback(mRecentsView::resetTaskVisuals)); - } - // In Overview, we may be layering app surfaces behind Launcher, so we need to notify - // DepthController to prevent optimizations which might occlude the layers behind - builder.addListener(AnimatorListeners.forSuccessCallback(() -> - mLauncher.getDepthController().setHasContentBehindLauncher( - toState.isRecentsViewVisible))); - - handleSplitSelectionState(toState, builder, /* animate */true); - - setAlphas(builder, config, toState); - builder.setFloat(mRecentsView, FULLSCREEN_PROGRESS, - toState.getOverviewFullscreenProgress(), LINEAR); - } - - /** - * 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 void handleSplitSelectionState(@NonNull LauncherState toState, - @NonNull PendingAnimation builder, boolean animate) { - boolean goingToOverviewFromWorkspaceContextual = enableSplitContextual() && - toState == OVERVIEW && mLauncher.isSplitSelectionActive(); - if (toState != OVERVIEW_SPLIT_SELECT && !goingToOverviewFromWorkspaceContextual) { - // Not going to split - return; - } - - // Create transition animations to split select - RecentsPagedOrientationHandler orientationHandler = - ((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler(); - Pair, FloatProperty> taskViewsFloat = - orientationHandler.getSplitSelectTaskOffset( - TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION, - mLauncher.getDeviceProfile()); - - SplitAnimationTimings timings = - AnimUtils.getDeviceOverviewToSplitTimings(mLauncher.getDeviceProfile().isTablet); - if (!goingToOverviewFromWorkspaceContextual) { - // This animation is already done for the contextual case, don't redo it - mRecentsView.createSplitSelectInitAnimation(builder, - toState.getTransitionDuration(mLauncher, true /* isToState */)); - } - // Shift tasks vertically downward to get out of placeholder view - builder.setFloat(mRecentsView, taskViewsFloat.first, - toState.getSplitSelectTranslation(mLauncher), - timings.getGridSlidePrimaryInterpolator()); - // Zero out horizontal translation - builder.setFloat(mRecentsView, taskViewsFloat.second, - 0, - timings.getGridSlideSecondaryInterpolator()); - - mRecentsView.handleDesktopTaskInSplitSelectState(builder, - timings.getDesktopTaskFadeInterpolator()); - - if (!animate) { - AnimatorSet as = builder.buildAnim(); - as.start(); - as.end(); - } - } - - private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config, - LauncherState state) { - float clearAllButtonAlpha = state.areElementsVisible(mLauncher, CLEAR_ALL_BUTTON) ? 1 : 0; - propertySetter.setFloat(mRecentsView.getClearAllButton(), ClearAllButton.VISIBILITY_ALPHA, - clearAllButtonAlpha, LINEAR); - float overviewButtonAlpha = state.areElementsVisible(mLauncher, OVERVIEW_ACTIONS) ? 1 : 0; - propertySetter.setFloat(mLauncher.getActionsView().getVisibilityAlpha(), - AnimatedFloat.VALUE, overviewButtonAlpha, config.getInterpolator( - ANIM_OVERVIEW_ACTIONS_FADE, LINEAR)); - } - - @Override - FloatProperty getTaskModalnessProperty() { - return TASK_MODALNESS; - } - - @Override - FloatProperty getContentAlphaProperty() { - return CONTENT_ALPHA; - } -} diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt new file mode 100644 index 0000000000..f1965481a1 --- /dev/null +++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.kt @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.android.launcher3.uioverrides + +import com.android.app.animation.Interpolators.ACCELERATE_DECELERATE +import com.android.app.animation.Interpolators.AGGRESSIVE_EASE_IN_OUT +import com.android.app.animation.Interpolators.FINAL_FRAME +import com.android.app.animation.Interpolators.INSTANT +import com.android.app.animation.Interpolators.LINEAR +import com.android.launcher3.Flags.enableLargeDesktopWindowingTile +import com.android.launcher3.LauncherState +import com.android.launcher3.anim.AnimatedFloat +import com.android.launcher3.anim.AnimatorListeners.forSuccessCallback +import com.android.launcher3.anim.PendingAnimation +import com.android.launcher3.anim.PropertySetter +import com.android.launcher3.config.FeatureFlags.enableSplitContextually +import com.android.launcher3.logging.StatsLogManager.LauncherEvent +import com.android.launcher3.statemanager.StateManager.StateHandler +import com.android.launcher3.states.StateAnimationConfig +import com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_ACTIONS_FADE +import com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE +import com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL +import com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE +import com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE +import com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X +import com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y +import com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW +import com.android.quickstep.util.AnimUtils +import com.android.quickstep.views.ClearAllButton +import com.android.quickstep.views.RecentsView +import com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET +import com.android.quickstep.views.RecentsView.CONTENT_ALPHA +import com.android.quickstep.views.RecentsView.DESKTOP_CAROUSEL_DETACH_PROGRESS +import com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS +import com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS +import com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY +import com.android.quickstep.views.RecentsView.TASK_MODALNESS +import com.android.quickstep.views.RecentsView.TASK_PRIMARY_SPLIT_TRANSLATION +import com.android.quickstep.views.RecentsView.TASK_SECONDARY_SPLIT_TRANSLATION +import com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION +import com.android.quickstep.views.RecentsView.TASK_THUMBNAIL_SPLASH_ALPHA +import com.android.quickstep.views.TaskView.Companion.FLAG_UPDATE_ALL +import com.android.wm.shell.Flags.enableSplitContextual + +/** + * State handler for handling UI changes for [com.android.quickstep.views.LauncherRecentsView]. In + * addition to managing the basic view properties, this class also manages changes in the task + * visuals. + */ +class RecentsViewStateController(private val launcher: QuickstepLauncher) : + StateHandler { + private val recentsView: RecentsView<*, *> = launcher.getOverviewPanel() + + override fun setState(state: LauncherState) { + val scaleAndOffset = state.getOverviewScaleAndOffset(launcher) + RECENTS_SCALE_PROPERTY.set(recentsView, scaleAndOffset[0]) + ADJACENT_PAGE_HORIZONTAL_OFFSET.set(recentsView, scaleAndOffset[1]) + TASK_SECONDARY_TRANSLATION.set(recentsView, 0f) + + CONTENT_ALPHA.set(recentsView, if (state.isRecentsViewVisible) 1f else 0f) + TASK_MODALNESS.set(recentsView, state.overviewModalness) + RECENTS_GRID_PROGRESS.set( + recentsView, + if (state.displayOverviewTasksAsGrid(launcher.deviceProfile)) 1f else 0f, + ) + TASK_THUMBNAIL_SPLASH_ALPHA.set( + recentsView, + if (state.showTaskThumbnailSplash()) 1f else 0f, + ) + if (enableLargeDesktopWindowingTile()) { + DESKTOP_CAROUSEL_DETACH_PROGRESS.set( + recentsView, + if (state.detachDesktopCarousel()) 1f else 0f, + ) + } + + if (state.isRecentsViewVisible) { + recentsView.updateEmptyMessage() + } else { + recentsView.resetTaskVisuals() + } + setAlphas(PropertySetter.NO_ANIM_PROPERTY_SETTER, StateAnimationConfig(), state) + recentsView.setFullscreenProgress(state.overviewFullscreenProgress) + // In Overview, we may be layering app surfaces behind Launcher, so we need to notify + // DepthController to prevent optimizations which might occlude the layers behind + launcher.depthController.setHasContentBehindLauncher(state.isRecentsViewVisible) + + val builder = PendingAnimation(state.getTransitionDuration(launcher, true).toLong()) + handleSplitSelectionState(state, builder, animate = false) + } + + override fun setStateWithAnimation( + toState: LauncherState, + config: StateAnimationConfig, + builder: PendingAnimation, + ) { + if (config.hasAnimationFlag(SKIP_OVERVIEW)) return + + val scaleAndOffset = toState.getOverviewScaleAndOffset(launcher) + builder.setFloat( + recentsView, + RECENTS_SCALE_PROPERTY, + scaleAndOffset[0], + config.getInterpolator(ANIM_OVERVIEW_SCALE, LINEAR), + ) + builder.setFloat( + recentsView, + ADJACENT_PAGE_HORIZONTAL_OFFSET, + scaleAndOffset[1], + config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_X, LINEAR), + ) + builder.setFloat( + recentsView, + TASK_SECONDARY_TRANSLATION, + 0f, + config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR), + ) + + val exitingOverview = !enableSplitContextually() && !toState.isRecentsViewVisible + if (recentsView.isSplitSelectionActive && exitingOverview) { + builder.add( + recentsView.splitSelectController.splitAnimationController + .createPlaceholderDismissAnim( + launcher, + LauncherEvent.LAUNCHER_SPLIT_SELECTION_EXIT_HOME, + builder.duration, + ) + ) + builder.setViewAlpha( + recentsView.splitInstructionsView, + 0f, + config.getInterpolator(ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE, LINEAR), + ) + } + + builder.setFloat( + recentsView, + CONTENT_ALPHA, + if (toState.isRecentsViewVisible) 1f else 0f, + config.getInterpolator(ANIM_OVERVIEW_FADE, AGGRESSIVE_EASE_IN_OUT), + ) + + builder.setFloat( + recentsView, + TASK_MODALNESS, + toState.overviewModalness, + config.getInterpolator(ANIM_OVERVIEW_MODAL, LINEAR), + ) + + val fromState = launcher.stateManager.state + builder.setFloat( + recentsView, + TASK_THUMBNAIL_SPLASH_ALPHA, + if (toState.showTaskThumbnailSplash()) 1f else 0f, + getOverviewInterpolator(fromState, toState), + ) + + builder.setFloat( + recentsView, + RECENTS_GRID_PROGRESS, + if (toState.displayOverviewTasksAsGrid(launcher.deviceProfile)) 1f else 0f, + getOverviewInterpolator(fromState, toState), + ) + + if (enableLargeDesktopWindowingTile()) { + builder.setFloat( + recentsView, + DESKTOP_CAROUSEL_DETACH_PROGRESS, + if (toState.detachDesktopCarousel()) 1f else 0f, + getOverviewInterpolator(fromState, toState), + ) + } + + if (toState.isRecentsViewVisible) { + // While animating into recents, update the visible task data as needed + builder.addOnFrameCallback { recentsView.loadVisibleTaskData(FLAG_UPDATE_ALL) } + recentsView.updateEmptyMessage() + } else { + builder.addListener(forSuccessCallback { recentsView.resetTaskVisuals() }) + } + // In Overview, we may be layering app surfaces behind Launcher, so we need to notify + // DepthController to prevent optimizations which might occlude the layers behind + builder.addListener( + forSuccessCallback { + launcher.depthController.setHasContentBehindLauncher(toState.isRecentsViewVisible) + } + ) + + handleSplitSelectionState(toState, builder, animate = true) + + setAlphas(builder, config, toState) + builder.setFloat( + recentsView, + FULLSCREEN_PROGRESS, + toState.overviewFullscreenProgress, + LINEAR, + ) + + builder.addEndListener { success: Boolean -> + if (!success && !toState.isRecentsViewVisible) { + recentsView.reset() + } + } + } + + /** + * 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 fun handleSplitSelectionState( + toState: LauncherState, + builder: PendingAnimation, + animate: Boolean, + ) { + val goingToOverviewFromWorkspaceContextual = + enableSplitContextual() && + toState == LauncherState.OVERVIEW && + launcher.isSplitSelectionActive + if ( + toState != LauncherState.OVERVIEW_SPLIT_SELECT && + !goingToOverviewFromWorkspaceContextual + ) { + // Not going to split + return + } + + // Create transition animations to split select + val orientationHandler = recentsView.pagedOrientationHandler + val taskViewsFloat = + orientationHandler.getSplitSelectTaskOffset( + TASK_PRIMARY_SPLIT_TRANSLATION, + TASK_SECONDARY_SPLIT_TRANSLATION, + launcher.deviceProfile, + ) + + val timings = AnimUtils.getDeviceOverviewToSplitTimings(launcher.deviceProfile.isTablet) + if (!goingToOverviewFromWorkspaceContextual) { + // This animation is already done for the contextual case, don't redo it + recentsView.createSplitSelectInitAnimation( + builder, + toState.getTransitionDuration(launcher, true), + ) + } + // Shift tasks vertically downward to get out of placeholder view + builder.setFloat( + recentsView, + taskViewsFloat.first, + toState.getSplitSelectTranslation(launcher), + timings.gridSlidePrimaryInterpolator, + ) + // Zero out horizontal translation + builder.setFloat( + recentsView, + taskViewsFloat.second, + 0f, + timings.gridSlideSecondaryInterpolator, + ) + + recentsView.handleDesktopTaskInSplitSelectState( + builder, + timings.desktopTaskFadeInterpolator, + ) + + if (!animate) { + builder.buildAnim().apply { + start() + end() + } + } + } + + private fun setAlphas( + propertySetter: PropertySetter, + config: StateAnimationConfig, + state: LauncherState, + ) { + val clearAllButtonAlpha = + if (state.areElementsVisible(launcher, LauncherState.CLEAR_ALL_BUTTON)) 1f else 0f + propertySetter.setFloat( + recentsView.clearAllButton, + ClearAllButton.VISIBILITY_ALPHA, + clearAllButtonAlpha, + LINEAR, + ) + val overviewButtonAlpha = + if (state.areElementsVisible(launcher, LauncherState.OVERVIEW_ACTIONS)) 1f else 0f + propertySetter.setFloat( + launcher.actionsView.visibilityAlpha, + AnimatedFloat.VALUE, + overviewButtonAlpha, + config.getInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, LINEAR), + ) + } + + private fun getOverviewInterpolator(fromState: LauncherState, toState: LauncherState) = + when { + fromState == LauncherState.QUICK_SWITCH_FROM_HOME -> ACCELERATE_DECELERATE + toState.isRecentsViewVisible -> INSTANT + else -> FINAL_FRAME + } +} diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java index daac9fb013..44fdaec4e2 100644 --- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java +++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java @@ -136,7 +136,7 @@ public class FallbackRecentsStateController implements StateHandler, FloatProperty> taskViewsFloat = + Pair>, FloatProperty>> taskViewsFloat = mRecentsView.getPagedOrientationHandler().getSplitSelectTaskOffset( TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION, mRecentsViewContainer.getDeviceProfile()); diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java index 4660c51ed2..bfa3f7c137 100644 --- a/quickstep/src/com/android/quickstep/views/RecentsView.java +++ b/quickstep/src/com/android/quickstep/views/RecentsView.java @@ -269,8 +269,8 @@ public abstract class RecentsView< private static final String TAG = "RecentsView"; private static final boolean DEBUG = false; - public static final FloatProperty CONTENT_ALPHA = - new FloatProperty("contentAlpha") { + public static final FloatProperty> CONTENT_ALPHA = + new FloatProperty<>("contentAlpha") { @Override public void setValue(RecentsView view, float v) { view.setContentAlpha(v); @@ -282,8 +282,8 @@ public abstract class RecentsView< } }; - public static final FloatProperty FULLSCREEN_PROGRESS = - new FloatProperty("fullscreenProgress") { + public static final FloatProperty> FULLSCREEN_PROGRESS = + new FloatProperty<>("fullscreenProgress") { @Override public void setValue(RecentsView recentsView, float v) { recentsView.setFullscreenProgress(v); @@ -295,8 +295,8 @@ public abstract class RecentsView< } }; - public static final FloatProperty TASK_MODALNESS = - new FloatProperty("taskModalness") { + public static final FloatProperty> TASK_MODALNESS = + new FloatProperty<>("taskModalness") { @Override public void setValue(RecentsView recentsView, float v) { recentsView.setTaskModalness(v); @@ -308,8 +308,8 @@ public abstract class RecentsView< } }; - public static final FloatProperty ADJACENT_PAGE_HORIZONTAL_OFFSET = - new FloatProperty("adjacentPageHorizontalOffset") { + public static final FloatProperty> ADJACENT_PAGE_HORIZONTAL_OFFSET = + new FloatProperty<>("adjacentPageHorizontalOffset") { @Override public void setValue(RecentsView recentsView, float v) { if (recentsView.mAdjacentPageHorizontalOffset != v) { @@ -324,8 +324,8 @@ public abstract class RecentsView< } }; - public static final FloatProperty RUNNING_TASK_ATTACH_ALPHA = - new FloatProperty("runningTaskAttachAlpha") { + public static final FloatProperty> RUNNING_TASK_ATTACH_ALPHA = + new FloatProperty<>("runningTaskAttachAlpha") { @Override public void setValue(RecentsView recentsView, float v) { recentsView.mRunningTaskAttachAlpha = v; @@ -349,8 +349,8 @@ public abstract class RecentsView< * Can be used to tint the color of the RecentsView to simulate a scrim that can views * excluded from. Really should be a proper scrim. */ - private static final FloatProperty COLOR_TINT = - new FloatProperty("colorTint") { + private static final FloatProperty> COLOR_TINT = + new FloatProperty<>("colorTint") { @Override public void setValue(RecentsView recentsView, float v) { recentsView.setColorTint(v); @@ -368,8 +368,8 @@ public abstract class RecentsView< * more specific, we'd want to create a similar FloatProperty just for a TaskView's * offsetX/Y property */ - public static final FloatProperty TASK_SECONDARY_TRANSLATION = - new FloatProperty("taskSecondaryTranslation") { + public static final FloatProperty> TASK_SECONDARY_TRANSLATION = + new FloatProperty<>("taskSecondaryTranslation") { @Override public void setValue(RecentsView recentsView, float v) { recentsView.setTaskViewsResistanceTranslation(v); @@ -387,8 +387,8 @@ public abstract class RecentsView< * more specific, we'd want to create a similar FloatProperty just for a TaskView's * offsetX/Y property */ - public static final FloatProperty TASK_PRIMARY_SPLIT_TRANSLATION = - new FloatProperty("taskPrimarySplitTranslation") { + public static final FloatProperty> TASK_PRIMARY_SPLIT_TRANSLATION = + new FloatProperty<>("taskPrimarySplitTranslation") { @Override public void setValue(RecentsView recentsView, float v) { recentsView.setTaskViewsPrimarySplitTranslation(v); @@ -400,8 +400,8 @@ public abstract class RecentsView< } }; - public static final FloatProperty TASK_SECONDARY_SPLIT_TRANSLATION = - new FloatProperty("taskSecondarySplitTranslation") { + public static final FloatProperty> TASK_SECONDARY_SPLIT_TRANSLATION = + new FloatProperty<>("taskSecondarySplitTranslation") { @Override public void setValue(RecentsView recentsView, float v) { recentsView.setTaskViewsSecondarySplitTranslation(v); @@ -414,8 +414,8 @@ public abstract class RecentsView< }; /** Same as normal SCALE_PROPERTY, but also updates page offsets that depend on this scale. */ - public static final FloatProperty RECENTS_SCALE_PROPERTY = - new FloatProperty("recentsScale") { + public static final FloatProperty> RECENTS_SCALE_PROPERTY = + new FloatProperty<>("recentsScale") { @Override public void setValue(RecentsView view, float scale) { view.setScaleX(scale); @@ -444,8 +444,8 @@ public abstract class RecentsView< * Progress of Recents view from carousel layout to grid layout. If Recents is not shown as a * grid, then the value remains 0. */ - public static final FloatProperty RECENTS_GRID_PROGRESS = - new FloatProperty("recentsGrid") { + public static final FloatProperty> RECENTS_GRID_PROGRESS = + new FloatProperty<>("recentsGrid") { @Override public void setValue(RecentsView view, float gridProgress) { view.setGridProgress(gridProgress); @@ -457,7 +457,7 @@ public abstract class RecentsView< } }; - public static final FloatProperty DESKTOP_CAROUSEL_DETACH_PROGRESS = + public static final FloatProperty> DESKTOP_CAROUSEL_DETACH_PROGRESS = new FloatProperty<>("desktopCarouselDetachProgress") { @Override public void setValue(RecentsView view, float offset) { @@ -476,8 +476,8 @@ public abstract class RecentsView< * Alpha of the task thumbnail splash, where being in BackgroundAppState has a value of 1, and * being in any other state has a value of 0. */ - public static final FloatProperty TASK_THUMBNAIL_SPLASH_ALPHA = - new FloatProperty("taskThumbnailSplashAlpha") { + public static final FloatProperty> TASK_THUMBNAIL_SPLASH_ALPHA = + new FloatProperty<>("taskThumbnailSplashAlpha") { @Override public void setValue(RecentsView view, float taskThumbnailSplashAlpha) { view.setTaskThumbnailSplashAlpha(taskThumbnailSplashAlpha); @@ -5484,7 +5484,7 @@ public abstract class RecentsView< firstFloatingTaskView.update(mTempRectF, /*progress=*/1f); RecentsPagedOrientationHandler orientationHandler = getPagedOrientationHandler(); - Pair, FloatProperty> taskViewsFloat = + Pair>, FloatProperty>> taskViewsFloat = orientationHandler.getSplitSelectTaskOffset( TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION, mContainer.getDeviceProfile());