Search in sources :

Example 11 with RemoteTargetHandle

use of com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle in project android_packages_apps_Launcher3 by ArrowOS.

the class RecentsView method createTaskDismissAnimation.

/**
 * Creates a {@link PendingAnimation} for dismissing the specified {@link TaskView}.
 * @param dismissedTaskView the {@link TaskView} to be dismissed
 * @param animateTaskView whether the {@link TaskView} to be dismissed should be animated
 * @param shouldRemoveTask whether the associated {@link Task} should be removed from
 *                         ActivityManager after dismissal
 * @param duration duration of the animation
 * @param dismissingForSplitSelection task dismiss animation is used for entering split
 *                                    selection state from app icon
 */
public PendingAnimation createTaskDismissAnimation(TaskView dismissedTaskView, boolean animateTaskView, boolean shouldRemoveTask, long duration, boolean dismissingForSplitSelection) {
    if (mPendingAnimation != null) {
        mPendingAnimation.createPlaybackController().dispatchOnCancel().dispatchOnEnd();
    }
    PendingAnimation anim = new PendingAnimation(duration);
    int count = getPageCount();
    if (count == 0) {
        return anim;
    }
    boolean showAsGrid = showAsGrid();
    int taskCount = getTaskViewCount();
    int dismissedIndex = indexOfChild(dismissedTaskView);
    int dismissedTaskViewId = dismissedTaskView.getTaskViewId();
    // Grid specific properties.
    boolean isFocusedTaskDismissed = false;
    TaskView nextFocusedTaskView = null;
    boolean nextFocusedTaskFromTop = false;
    float dismissedTaskWidth = 0;
    float nextFocusedTaskWidth = 0;
    // Non-grid specific properties.
    int[] oldScroll = new int[count];
    int[] newScroll = new int[count];
    int scrollDiffPerPage = 0;
    boolean needsCurveUpdates = false;
    if (showAsGrid) {
        dismissedTaskWidth = dismissedTaskView.getLayoutParams().width + mPageSpacing;
        isFocusedTaskDismissed = dismissedTaskViewId == mFocusedTaskViewId;
        if (isFocusedTaskDismissed && !isSplitSelectionActive()) {
            nextFocusedTaskFromTop = mTopRowIdSet.size() > 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f;
            // Pick the next focused task from the preferred row.
            for (int i = 0; i < taskCount; i++) {
                TaskView taskView = requireTaskViewAt(i);
                if (taskView == dismissedTaskView) {
                    continue;
                }
                boolean isTopRow = mTopRowIdSet.contains(taskView.getTaskViewId());
                if ((nextFocusedTaskFromTop && isTopRow || (!nextFocusedTaskFromTop && !isTopRow))) {
                    nextFocusedTaskView = taskView;
                    break;
                }
            }
            if (nextFocusedTaskView != null) {
                nextFocusedTaskWidth = nextFocusedTaskView.getLayoutParams().width + mPageSpacing;
            }
        }
    } else {
        getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC);
        getPageScrolls(newScroll, false, v -> v.getVisibility() != GONE && v != dismissedTaskView);
        if (count > 1) {
            scrollDiffPerPage = Math.abs(oldScroll[1] - oldScroll[0]);
        }
    }
    announceForAccessibility(getResources().getString(R.string.task_view_closed));
    float dismissTranslationInterpolationEnd = 1;
    boolean closeGapBetweenClearAll = false;
    boolean isClearAllHidden = isClearAllHidden();
    boolean snapToLastTask = false;
    boolean isLandscapeSplit = mActivity.getDeviceProfile().isLandscape && isSplitSelectionActive();
    boolean isSplitPlaceholderFirstInGrid = isSplitPlaceholderFirstInGrid();
    boolean isSplitPlaceholderLastInGrid = isSplitPlaceholderLastInGrid();
    TaskView lastGridTaskView = showAsGrid ? getLastGridTaskView() : null;
    int currentPageScroll = getScrollForPage(mCurrentPage);
    int lastGridTaskScroll = getScrollForPage(indexOfChild(lastGridTaskView));
    boolean currentPageSnapsToEndOfGrid = currentPageScroll == lastGridTaskScroll;
    if (lastGridTaskView != null && lastGridTaskView.isVisibleToUser()) {
        // After dismissal, animate translation of the remaining tasks to fill any gap left
        // between the end of the grid and the clear all button. Only animate if the clear
        // all button is visible or would become visible after dismissal.
        float longGridRowWidthDiff = 0;
        int topGridRowSize = mTopRowIdSet.size();
        int bottomGridRowSize = taskCount - mTopRowIdSet.size() - 1;
        boolean topRowLonger = topGridRowSize > bottomGridRowSize;
        boolean bottomRowLonger = bottomGridRowSize > topGridRowSize;
        boolean dismissedTaskFromTop = mTopRowIdSet.contains(dismissedTaskViewId);
        boolean dismissedTaskFromBottom = !dismissedTaskFromTop && !isFocusedTaskDismissed;
        float gapWidth = 0;
        if ((topRowLonger && dismissedTaskFromTop) || (bottomRowLonger && dismissedTaskFromBottom)) {
            gapWidth = dismissedTaskWidth;
        } else if ((topRowLonger && nextFocusedTaskFromTop) || (bottomRowLonger && !nextFocusedTaskFromTop)) {
            gapWidth = nextFocusedTaskWidth;
        }
        if (gapWidth > 0) {
            if (taskCount > 2) {
                // Compensate the removed gap.
                longGridRowWidthDiff += mIsRtl ? -gapWidth : gapWidth;
                if (isClearAllHidden) {
                    // If ClearAllButton isn't fully shown, snap to the last task.
                    snapToLastTask = true;
                }
            } else {
                // If only focused task will be left, snap to focused task instead.
                longGridRowWidthDiff += getSnapToFocusedTaskScrollDiff(isClearAllHidden);
            }
        }
        if (mClearAllButton.getAlpha() != 0f && isLandscapeSplit) {
            // ClearAllButton will not be available in split select, snap to last task instead.
            snapToLastTask = true;
        }
        if (snapToLastTask) {
            longGridRowWidthDiff += getSnapToLastTaskScrollDiff();
            if (isSplitPlaceholderLastInGrid) {
                // Shift all the tasks to make space for split placeholder.
                longGridRowWidthDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
            }
        } else if (isLandscapeSplit && currentPageSnapsToEndOfGrid) {
            // Use last task as reference point for scroll diff and snapping calculation as it's
            // the only invariant point in landscape split screen.
            snapToLastTask = true;
        }
        // fake it using interpolation.
        if (longGridRowWidthDiff != 0) {
            closeGapBetweenClearAll = true;
            // Stagger the offsets of each additional task for a delayed animation. We use
            // half here as this animation is half of half of an animation (1/4th).
            float halfAdditionalDismissTranslationOffset = (0.5f * ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET);
            dismissTranslationInterpolationEnd = Utilities.boundToRange(END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + (taskCount - 1) * halfAdditionalDismissTranslationOffset, END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET, 1);
            for (int i = 0; i < taskCount; i++) {
                TaskView taskView = requireTaskViewAt(i);
                anim.setFloat(taskView, TaskView.GRID_END_TRANSLATION_X, longGridRowWidthDiff, clampToProgress(LINEAR, dismissTranslationInterpolationEnd, 1));
                dismissTranslationInterpolationEnd = Utilities.boundToRange(dismissTranslationInterpolationEnd - halfAdditionalDismissTranslationOffset, END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET, 1);
                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && taskView.isRunningTask()) {
                    anim.addOnFrameCallback(() -> {
                        runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().taskPrimaryTranslation.value = TaskView.GRID_END_TRANSLATION_X.get(taskView));
                        redrawLiveTile();
                    });
                }
            }
            // Change alpha of clear all if translating grid to hide it
            if (isClearAllHidden) {
                anim.setFloat(mClearAllButton, DISMISS_ALPHA, 0, LINEAR);
                anim.addListener(new AnimatorListenerAdapter() {

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        mClearAllButton.setDismissAlpha(1);
                    }
                });
            }
        }
    }
    int distanceFromDismissedTask = 0;
    for (int i = 0; i < count; i++) {
        View child = getChildAt(i);
        if (child == dismissedTaskView) {
            if (animateTaskView) {
                if (dismissingForSplitSelection) {
                    createInitialSplitSelectAnimation(anim);
                } else {
                    addDismissedTaskAnimations(dismissedTaskView, duration, anim);
                }
            }
        } else if (!showAsGrid) {
            // Compute scroll offsets from task dismissal for animation.
            // If we just take newScroll - oldScroll, everything to the right of dragged task
            // translates to the left. We need to offset this in some cases:
            // - In RTL, add page offset to all pages, since we want pages to move to the right
            // Additionally, add a page offset if:
            // - Current page is rightmost page (leftmost for RTL)
            // - Dragging an adjacent page on the left side (right side for RTL)
            int offset = mIsRtl ? scrollDiffPerPage : 0;
            if (mCurrentPage == dismissedIndex) {
                int lastPage = taskCount - 1;
                if (mCurrentPage == lastPage) {
                    offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
                }
            } else {
                // Dismissing an adjacent page.
                // (Right in RTL, left in LTR)
                int negativeAdjacent = mCurrentPage - 1;
                if (dismissedIndex == negativeAdjacent) {
                    offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
                }
            }
            int scrollDiff = newScroll[i] - oldScroll[i] + offset;
            if (scrollDiff != 0) {
                FloatProperty translationProperty = child instanceof TaskView ? ((TaskView) child).getPrimaryDismissTranslationProperty() : mOrientationHandler.getPrimaryViewTranslate();
                float additionalDismissDuration = ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * Math.abs(i - dismissedIndex);
                anim.setFloat(child, translationProperty, scrollDiff, clampToProgress(LINEAR, Utilities.boundToRange(INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + additionalDismissDuration, 0f, 1f), 1));
                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && child instanceof TaskView && ((TaskView) child).isRunningTask()) {
                    anim.addOnFrameCallback(() -> {
                        runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().taskPrimaryTranslation.value = mOrientationHandler.getPrimaryValue(child.getTranslationX(), child.getTranslationY()));
                        redrawLiveTile();
                    });
                }
                needsCurveUpdates = true;
            }
        } else if (child instanceof TaskView) {
            TaskView taskView = (TaskView) child;
            if (isFocusedTaskDismissed) {
                if (nextFocusedTaskView != null && !isSameGridRow(taskView, nextFocusedTaskView)) {
                    continue;
                }
            } else {
                if (i < dismissedIndex || !isSameGridRow(taskView, dismissedTaskView)) {
                    continue;
                }
            }
            // Animate task with index >= dismissed index and in the same row as the
            // dismissed index or next focused index. Offset successive task dismissal
            // durations for a staggered effect.
            float animationStartProgress = Utilities.boundToRange(INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * ++distanceFromDismissedTask, 0f, dismissTranslationInterpolationEnd);
            if (taskView == nextFocusedTaskView) {
                // Enlarge the task to be focused next, and translate into focus position.
                float scale = mTaskWidth / (float) mLastComputedGridTaskSize.width();
                anim.setFloat(taskView, TaskView.SNAPSHOT_SCALE, scale, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), mIsRtl ? dismissedTaskWidth : -dismissedTaskWidth, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                float secondaryTranslation = -mTaskGridVerticalDiff;
                if (!nextFocusedTaskFromTop) {
                    secondaryTranslation -= mTopBottomRowHeightDiff;
                }
                anim.setFloat(taskView, taskView.getSecondaryDissmissTranslationProperty(), secondaryTranslation, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                anim.setFloat(taskView, TaskView.FOCUS_TRANSITION, 0f, clampToProgress(LINEAR, 0f, ANIMATION_DISMISS_PROGRESS_MIDPOINT));
            } else {
                float primaryTranslation = nextFocusedTaskView != null ? nextFocusedTaskWidth : dismissedTaskWidth;
                if (isFocusedTaskDismissed && nextFocusedTaskView == null) {
                    // Moves less if focused task is not in scroll position.
                    int focusedTaskScroll = getScrollForPage(dismissedIndex);
                    int primaryScroll = mOrientationHandler.getPrimaryScroll(this);
                    int focusedTaskScrollDiff = primaryScroll - focusedTaskScroll;
                    primaryTranslation += mIsRtl ? focusedTaskScrollDiff : -focusedTaskScrollDiff;
                    if (isSplitPlaceholderFirstInGrid) {
                        // Moves less if split placeholder is at the start.
                        primaryTranslation += mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
                    }
                }
                anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), mIsRtl ? primaryTranslation : -primaryTranslation, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
            }
        }
    }
    if (needsCurveUpdates) {
        anim.addOnFrameCallback(this::updateCurveProperties);
    }
    // Add a tiny bit of translation Z, so that it draws on top of other views
    if (animateTaskView) {
        dismissedTaskView.setTranslationZ(0.1f);
    }
    mPendingAnimation = anim;
    final TaskView finalNextFocusedTaskView = nextFocusedTaskView;
    final boolean finalCloseGapBetweenClearAll = closeGapBetweenClearAll;
    final boolean finalSnapToLastTask = snapToLastTask;
    final boolean finalIsFocusedTaskDismissed = isFocusedTaskDismissed;
    mPendingAnimation.addEndListener(new Consumer<Boolean>() {

        @Override
        public void accept(Boolean success) {
            if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && dismissedTaskView.isRunningTask() && success) {
                finishRecentsAnimation(true, /* toRecents */
                false, /* shouldPip */
                () -> onEnd(success));
            } else {
                onEnd(success);
            }
        }

        @SuppressWarnings("WrongCall")
        private void onEnd(boolean success) {
            // Reset task translations as they may have updated via animations in
            // createTaskDismissAnimation
            resetTaskVisuals();
            if (success) {
                if (shouldRemoveTask) {
                    if (dismissedTaskView.getTask() != null) {
                        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && dismissedTaskView.isRunningTask()) {
                            finishRecentsAnimation(true, /* toRecents */
                            false, /* shouldPip */
                            () -> removeTaskInternal(dismissedTaskViewId));
                        } else {
                            removeTaskInternal(dismissedTaskViewId);
                        }
                        mActivity.getStatsLogManager().logger().withItemInfo(dismissedTaskView.getItemInfo()).log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
                    }
                }
                int pageToSnapTo = mCurrentPage;
                mCurrentPageScrollDiff = 0;
                int taskViewIdToSnapTo = -1;
                if (showAsGrid) {
                    if (finalCloseGapBetweenClearAll) {
                        if (finalSnapToLastTask) {
                            // Last task will be determined after removing dismissed task.
                            pageToSnapTo = -1;
                        } else if (taskCount > 2) {
                            pageToSnapTo = indexOfChild(mClearAllButton);
                        } else if (isClearAllHidden) {
                            // Snap to focused task if clear all is hidden.
                            pageToSnapTo = 0;
                        }
                    } else {
                        // Get the id of the task view we will snap to based on the current
                        // page's relative position as the order of indices change over time due
                        // to dismissals.
                        TaskView snappedTaskView = getTaskViewAt(mCurrentPage);
                        boolean calculateScrollDiff = true;
                        if (snappedTaskView != null && !finalSnapToLastTask) {
                            if (snappedTaskView.getTaskViewId() == mFocusedTaskViewId) {
                                if (finalNextFocusedTaskView != null) {
                                    taskViewIdToSnapTo = finalNextFocusedTaskView.getTaskViewId();
                                } else if (dismissedTaskViewId != mFocusedTaskViewId) {
                                    taskViewIdToSnapTo = mFocusedTaskViewId;
                                } else {
                                    // Won't focus next task in split select, so snap to the
                                    // first task.
                                    pageToSnapTo = 0;
                                    calculateScrollDiff = false;
                                }
                            } else {
                                int snappedTaskViewId = snappedTaskView.getTaskViewId();
                                boolean isSnappedTaskInTopRow = mTopRowIdSet.contains(snappedTaskViewId);
                                IntArray taskViewIdArray = isSnappedTaskInTopRow ? getTopRowIdArray() : getBottomRowIdArray();
                                int snappedIndex = taskViewIdArray.indexOf(snappedTaskViewId);
                                taskViewIdArray.removeValue(dismissedTaskViewId);
                                if (finalNextFocusedTaskView != null) {
                                    taskViewIdArray.removeValue(finalNextFocusedTaskView.getTaskViewId());
                                }
                                if (snappedIndex < taskViewIdArray.size()) {
                                    taskViewIdToSnapTo = taskViewIdArray.get(snappedIndex);
                                } else if (snappedIndex == taskViewIdArray.size()) {
                                    // If the snapped task is the last item from the
                                    // dismissed row,
                                    // snap to the same column in the other grid row
                                    IntArray inverseRowTaskViewIdArray = isSnappedTaskInTopRow ? getBottomRowIdArray() : getTopRowIdArray();
                                    if (snappedIndex < inverseRowTaskViewIdArray.size()) {
                                        taskViewIdToSnapTo = inverseRowTaskViewIdArray.get(snappedIndex);
                                    }
                                }
                            }
                        }
                        if (calculateScrollDiff) {
                            int primaryScroll = mOrientationHandler.getPrimaryScroll(RecentsView.this);
                            int currentPageScroll = getScrollForPage(mCurrentPage);
                            mCurrentPageScrollDiff = primaryScroll - currentPageScroll;
                            // Compensate for coordinate shift by split placeholder.
                            if (isSplitPlaceholderFirstInGrid && !finalSnapToLastTask) {
                                mCurrentPageScrollDiff += mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
                            } else if (isSplitPlaceholderLastInGrid && finalSnapToLastTask) {
                                mCurrentPageScrollDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
                            }
                        }
                    }
                } else if (dismissedIndex < pageToSnapTo || pageToSnapTo == taskCount - 1) {
                    pageToSnapTo--;
                }
                boolean isHomeTaskDismissed = dismissedTaskView == getHomeTaskView();
                removeViewInLayout(dismissedTaskView);
                mTopRowIdSet.remove(dismissedTaskViewId);
                if (taskCount == 1) {
                    removeViewInLayout(mClearAllButton);
                    if (isHomeTaskDismissed) {
                        updateEmptyMessage();
                    } else {
                        startHome();
                    }
                } else {
                    // Update focus task and its size.
                    if (finalIsFocusedTaskDismissed && finalNextFocusedTaskView != null) {
                        mFocusedTaskViewId = finalNextFocusedTaskView.getTaskViewId();
                        mTopRowIdSet.remove(mFocusedTaskViewId);
                        finalNextFocusedTaskView.animateIconScaleAndDimIntoView();
                    }
                    updateTaskSize(/*isTaskDismissal=*/
                    true);
                    updateChildTaskOrientations();
                    // Update scroll and snap to page.
                    updateScrollSynchronously();
                    if (showAsGrid) {
                        // Rebalance tasks in the grid
                        int highestVisibleTaskIndex = getHighestVisibleTaskIndex();
                        if (highestVisibleTaskIndex < Integer.MAX_VALUE) {
                            TaskView taskView = requireTaskViewAt(highestVisibleTaskIndex);
                            boolean shouldRebalance;
                            int screenStart = mOrientationHandler.getPrimaryScroll(RecentsView.this);
                            int taskStart = mOrientationHandler.getChildStart(taskView) + (int) taskView.getOffsetAdjustment(/*fullscreenEnabled=*/
                            false, /*gridEnabled=*/
                            true);
                            // visible screen.
                            if (mIsRtl) {
                                shouldRebalance = taskStart <= screenStart + mPageSpacing;
                            } else {
                                int screenEnd = screenStart + mOrientationHandler.getMeasuredSize(RecentsView.this);
                                int taskSize = (int) (mOrientationHandler.getMeasuredSize(taskView) * taskView.getSizeAdjustment(/*fullscreenEnabled=*/
                                false));
                                int taskEnd = taskStart + taskSize;
                                shouldRebalance = taskEnd >= screenEnd - mPageSpacing;
                            }
                            if (shouldRebalance) {
                                updateGridProperties(/*isTaskDismissal=*/
                                true, highestVisibleTaskIndex);
                                updateScrollSynchronously();
                            }
                        }
                        IntArray topRowIdArray = getTopRowIdArray();
                        IntArray bottomRowIdArray = getBottomRowIdArray();
                        if (finalSnapToLastTask) {
                            // If snapping to last task, find the last task after dismissal.
                            pageToSnapTo = indexOfChild(getLastGridTaskView(topRowIdArray, bottomRowIdArray));
                        } else if (taskViewIdToSnapTo != -1) {
                            // If snapping to another page due to indices rearranging, find
                            // the new index after dismissal & rearrange using the task view id.
                            pageToSnapTo = indexOfChild(getTaskViewFromTaskViewId(taskViewIdToSnapTo));
                            if (!currentPageSnapsToEndOfGrid) {
                                // If it wasn't snapped to one of the last pages, but is now
                                // snapped to last pages, we'll need to compensate for the
                                // offset from the page's scroll to its visual position.
                                mCurrentPageScrollDiff += getOffsetFromScrollPosition(pageToSnapTo, topRowIdArray, bottomRowIdArray);
                            }
                        }
                    }
                    pageBeginTransition();
                    setCurrentPage(pageToSnapTo);
                    // Update various scroll-dependent UI.
                    dispatchScrollChanged();
                    updateActionsViewFocusedScroll();
                    if (isClearAllHidden()) {
                        mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
                    }
                }
            }
            updateCurrentTaskActionsVisibility();
            onDismissAnimationEnds();
            mPendingAnimation = null;
        }
    });
    return anim;
}
Also used : BACKGROUND_APP(com.android.launcher3.LauncherState.BACKGROUND_APP) RemoteTargetGluer(com.android.quickstep.RemoteTargetGluer) HIDDEN_NO_TASKS(com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS) Bundle(android.os.Bundle) Overrides(com.android.launcher3.util.ResourceBasedOverride.Overrides) NonNull(androidx.annotation.NonNull) AnimatorListeners(com.android.launcher3.anim.AnimatorListeners) AccessibilityManagerCompat(com.android.launcher3.compat.AccessibilityManagerCompat) BaseActivityInterface(com.android.quickstep.BaseActivityInterface) Drawable(android.graphics.drawable.Drawable) TaskViewSimulator(com.android.quickstep.util.TaskViewSimulator) LayoutTransition(android.animation.LayoutTransition) PropertyValuesHolder(android.animation.PropertyValuesHolder) TaskStackChangeListeners(com.android.systemui.shared.system.TaskStackChangeListeners) UiThread(androidx.annotation.UiThread) Canvas(android.graphics.Canvas) LayoutUtils(com.android.quickstep.util.LayoutUtils) AccessibilityEvent(android.view.accessibility.AccessibilityEvent) TargetApi(android.annotation.TargetApi) Log(android.util.Log) TaskVisualsChangeListener(com.android.quickstep.RecentsModel.TaskVisualsChangeListener) RecentsAnimationTargets(com.android.quickstep.RecentsAnimationTargets) HIDDEN_NO_RECENTS(com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS) Interpolator(android.view.animation.Interpolator) HIDDEN_NON_ZERO_ROTATION(com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION) AnimatorListenerAdapter(android.animation.AnimatorListenerAdapter) DeviceProfile(com.android.launcher3.DeviceProfile) HapticFeedbackConstants(android.view.HapticFeedbackConstants) LAUNCHER_TASK_LAUNCH_SWIPE_DOWN(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN) Nullable(androidx.annotation.Nullable) UI_STATE_FULLSCREEN_TASK(com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK) Layout(android.text.Layout) MultiWindowModeChangedListener(com.android.launcher3.BaseActivity.MultiWindowModeChangedListener) TextPaint(android.text.TextPaint) AbstractFloatingView.getTopOpenViewWithType(com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType) RemoteAnimationTargetCompat(com.android.systemui.shared.system.RemoteAnimationTargetCompat) TaskKey(com.android.systemui.shared.recents.model.Task.TaskKey) Insettable(com.android.launcher3.Insettable) SystemClock(android.os.SystemClock) Utilities.squaredTouchSlop(com.android.launcher3.Utilities.squaredTouchSlop) SystemUiProxy(com.android.quickstep.SystemUiProxy) CANVAS_TRANSLATE(com.android.launcher3.touch.PagedOrientationHandler.CANVAS_TRANSLATE) RemoteAnimationTargets(com.android.quickstep.RemoteAnimationTargets) ArrayList(java.util.ArrayList) TransformParams(com.android.quickstep.util.TransformParams) TaskUtils.checkCurrentOrManagedUserId(com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId) SplitScreenBounds(com.android.quickstep.util.SplitScreenBounds) VibrationEffect(android.os.VibrationEffect) UserHandle(android.os.UserHandle) Toast(android.widget.Toast) Utilities.mapToRange(com.android.launcher3.Utilities.mapToRange) DEPTH(com.android.launcher3.statehandlers.DepthController.DEPTH) LocusId(android.content.LocusId) IntArray(com.android.launcher3.util.IntArray) MeasureSpec.makeMeasureSpec(android.view.View.MeasureSpec.makeMeasureSpec) DISMISS_ALPHA(com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA) BaseState(com.android.launcher3.statemanager.BaseState) SpringProperty(com.android.launcher3.anim.SpringProperty) OverScroll(com.android.launcher3.touch.OverScroll) ViewPool(com.android.launcher3.util.ViewPool) ViewDebug(android.view.ViewDebug) FeatureFlags(com.android.launcher3.config.FeatureFlags) DynamicResource(com.android.launcher3.util.DynamicResource) SUCCESS_TRANSITION_PROGRESS(com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS) LINEAR(com.android.launcher3.anim.Interpolators.LINEAR) IntSet(com.android.launcher3.util.IntSet) SparseBooleanArray(android.util.SparseBooleanArray) HandlerRunnable(com.android.launcher3.icons.cache.HandlerRunnable) R(com.android.launcher3.R) TranslateEdgeEffect(com.android.launcher3.util.TranslateEdgeEffect) Configuration(android.content.res.Configuration) ColorUtils(androidx.core.graphics.ColorUtils) RunnableList(com.android.launcher3.util.RunnableList) ACCEL(com.android.launcher3.anim.Interpolators.ACCEL) ValueAnimator(android.animation.ValueAnimator) Rect(android.graphics.Rect) PackageManagerWrapper(com.android.systemui.shared.system.PackageManagerWrapper) PointF(android.graphics.PointF) StagedSplitBounds(com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds) Task(com.android.systemui.shared.recents.model.Task) Interpolators.clampToProgress(com.android.launcher3.anim.Interpolators.clampToProgress) RECENTS_LAUNCH_DURATION(com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION) Animator(android.animation.Animator) STAGE_POSITION_TOP_OR_LEFT(com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) FloatProperty(android.util.FloatProperty) AttributeSet(android.util.AttributeSet) ActivityManagerWrapper(com.android.systemui.shared.system.ActivityManagerWrapper) TaskViewUtils(com.android.quickstep.TaskViewUtils) STAGE_POSITION_BOTTOM_OR_RIGHT(com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT) MAIN_EXECUTOR(com.android.launcher3.util.Executors.MAIN_EXECUTOR) View(android.view.View) VibratorWrapper(com.android.quickstep.util.VibratorWrapper) Matrix(android.graphics.Matrix) RectF(android.graphics.RectF) OverScroller(android.widget.OverScroller) Utilities(com.android.launcher3.Utilities) AnimatedFloat(com.android.quickstep.AnimatedFloat) TransitionListener(android.animation.LayoutTransition.TransitionListener) UI_HELPER_EXECUTOR(com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR) DepthController(com.android.launcher3.statehandlers.DepthController) ObjectAnimator(android.animation.ObjectAnimator) EDGE_NAV_BAR(com.android.launcher3.Utilities.EDGE_NAV_BAR) TaskStackChangeListener(com.android.systemui.shared.system.TaskStackChangeListener) ROTATION_0(android.view.Surface.ROTATION_0) ViewGroup(android.view.ViewGroup) MultiValueAlpha(com.android.launcher3.util.MultiValueAlpha) SplitSelectStateController(com.android.quickstep.util.SplitSelectStateController) Objects(java.util.Objects) List(java.util.List) OnScrollChangedListener(android.view.ViewTreeObserver.OnScrollChangedListener) HIDDEN_SPLIT_SCREEN(com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN) ThumbnailData(com.android.systemui.shared.recents.model.ThumbnailData) RemoteTargetHandle(com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle) ListView(android.widget.ListView) Themes(com.android.launcher3.util.Themes) SurfaceTransactionApplier(com.android.quickstep.util.SurfaceTransactionApplier) TYPE_TASK_MENU(com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU) IPipAnimationListener(com.android.wm.shell.pip.IPipAnimationListener) ACCEL_DEACCEL(com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL) Typeface(android.graphics.Typeface) Context(android.content.Context) StaticLayout(android.text.StaticLayout) AccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo) TaskThumbnailCache(com.android.quickstep.TaskThumbnailCache) KeyEvent(android.view.KeyEvent) LAUNCHER_TASK_CLEAR_ALL(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL) RunningTaskInfo(android.app.ActivityManager.RunningTaskInfo) EXACTLY(android.view.View.MeasureSpec.EXACTLY) STATE_HANDLER_INVISIBILITY_FLAGS(com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS) Pair(android.util.Pair) LAUNCHER_TASK_DISMISS_SWIPE_UP(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP) HashMap(java.util.HashMap) FAST_OUT_SLOW_IN(com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN) AnimatorPlaybackController(com.android.launcher3.anim.AnimatorPlaybackController) Utilities.squaredHypot(com.android.launcher3.Utilities.squaredHypot) ENABLE_QUICKSTEP_LIVE_TILE(com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE) MotionEvent(android.view.MotionEvent) BaseActivity(com.android.launcher3.BaseActivity) AnimatorSet(android.animation.AnimatorSet) Build(android.os.Build) TaskOverlayFactory(com.android.quickstep.TaskOverlayFactory) SurfaceParams(com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams) GroupTask(com.android.quickstep.util.GroupTask) LayoutInflater(android.view.LayoutInflater) GestureState(com.android.quickstep.GestureState) RecentsAnimationController(com.android.quickstep.RecentsAnimationController) TASK_VIEW_ID_CRASH(com.android.launcher3.testing.TestProtocol.TASK_VIEW_ID_CRASH) StatefulActivity(com.android.launcher3.statemanager.StatefulActivity) Point(android.graphics.Point) RecentsOrientedState(com.android.quickstep.util.RecentsOrientedState) ResourceProvider(com.android.systemui.plugins.ResourceProvider) VIEW_ALPHA(com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA) BlendMode(android.graphics.BlendMode) Color(android.graphics.Color) Consumer(java.util.function.Consumer) InvariantDeviceProfile(com.android.launcher3.InvariantDeviceProfile) FINAL_FRAME(com.android.launcher3.anim.Interpolators.FINAL_FRAME) RecentsModel(com.android.quickstep.RecentsModel) PagedView(com.android.launcher3.PagedView) ACCEL_0_75(com.android.launcher3.anim.Interpolators.ACCEL_0_75) PagedOrientationHandler(com.android.launcher3.touch.PagedOrientationHandler) StagePosition(com.android.launcher3.util.SplitConfigurationOptions.StagePosition) PendingAnimation(com.android.launcher3.anim.PendingAnimation) ViewUtils(com.android.quickstep.ViewUtils) PendingAnimation(com.android.launcher3.anim.PendingAnimation) View(android.view.View) ListView(android.widget.ListView) PagedView(com.android.launcher3.PagedView) TextPaint(android.text.TextPaint) Point(android.graphics.Point) ValueAnimator(android.animation.ValueAnimator) Animator(android.animation.Animator) ObjectAnimator(android.animation.ObjectAnimator) IntArray(com.android.launcher3.util.IntArray) AnimatorListenerAdapter(android.animation.AnimatorListenerAdapter) FloatProperty(android.util.FloatProperty)

Example 12 with RemoteTargetHandle

use of com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle in project android_packages_apps_Launcher3 by ArrowOS.

the class TaskViewUtils method createRecentsWindowAnimator.

public static void createRecentsWindowAnimator(@NonNull TaskView v, boolean skipViewChanges, @NonNull RemoteAnimationTargetCompat[] appTargets, @NonNull RemoteAnimationTargetCompat[] wallpaperTargets, @NonNull RemoteAnimationTargetCompat[] nonAppTargets, @Nullable DepthController depthController, PendingAnimation out) {
    RecentsView recentsView = v.getRecentsView();
    boolean isQuickSwitch = v.isEndQuickswitchCuj();
    v.setEndQuickswitchCuj(false);
    boolean inLiveTileMode = ENABLE_QUICKSTEP_LIVE_TILE.get() && v.getRecentsView().getRunningTaskIndex() != -1;
    final RemoteAnimationTargets targets = new RemoteAnimationTargets(appTargets, wallpaperTargets, nonAppTargets, inLiveTileMode ? MODE_CLOSING : MODE_OPENING);
    final RemoteAnimationTargetCompat navBarTarget = targets.getNavBarRemoteAnimationTarget();
    SurfaceTransactionApplier applier = new SurfaceTransactionApplier(v);
    targets.addReleaseCheck(applier);
    RemoteTargetHandle[] remoteTargetHandles;
    RemoteTargetHandle[] recentsViewHandles = recentsView.getRemoteTargetHandles();
    if (v.isRunningTask() && recentsViewHandles != null) {
        // Re-use existing handles
        remoteTargetHandles = recentsViewHandles;
    } else {
        RemoteTargetGluer gluer = new RemoteTargetGluer(v.getContext(), recentsView.getSizeStrategy(), targets);
        if (v.containsMultipleTasks()) {
            remoteTargetHandles = gluer.assignTargetsForSplitScreen(targets, v.getTaskIds());
        } else {
            remoteTargetHandles = gluer.assignTargets(targets);
        }
    }
    for (RemoteTargetHandle remoteTargetGluer : remoteTargetHandles) {
        remoteTargetGluer.getTransformParams().setSyncTransactionApplier(applier);
    }
    int taskIndex = recentsView.indexOfChild(v);
    Context context = v.getContext();
    DeviceProfile dp = BaseActivity.fromContext(context).getDeviceProfile();
    boolean showAsGrid = dp.overviewShowAsGrid;
    boolean parallaxCenterAndAdjacentTask = taskIndex != recentsView.getCurrentPage() && !showAsGrid;
    int taskRectTranslationPrimary = recentsView.getScrollOffset(taskIndex);
    int taskRectTranslationSecondary = showAsGrid ? (int) v.getGridTranslationY() : 0;
    RemoteTargetHandle[] topMostSimulators = null;
    if (!v.isRunningTask()) {
        // TVSs already initialized from the running task, no need to re-init
        for (RemoteTargetHandle targetHandle : remoteTargetHandles) {
            TaskViewSimulator tvsLocal = targetHandle.getTaskViewSimulator();
            tvsLocal.setDp(dp);
            // RecentsView never updates the display rotation until swipe-up so the value may
            // be stale. Use the display value instead.
            int displayRotation = DisplayController.INSTANCE.get(context).getInfo().rotation;
            tvsLocal.getOrientationState().update(displayRotation, displayRotation);
            tvsLocal.fullScreenProgress.value = 0;
            tvsLocal.recentsViewScale.value = 1;
            tvsLocal.setIsGridTask(v.isGridTask());
            tvsLocal.getOrientationState().getOrientationHandler().set(tvsLocal, TaskViewSimulator::setTaskRectTranslation, taskRectTranslationPrimary, taskRectTranslationSecondary);
            // Fade in the task during the initial 20% of the animation
            out.addFloat(targetHandle.getTransformParams(), TransformParams.TARGET_ALPHA, 0, 1, clampToProgress(LINEAR, 0, 0.2f));
        }
    }
    for (RemoteTargetHandle targetHandle : remoteTargetHandles) {
        TaskViewSimulator tvsLocal = targetHandle.getTaskViewSimulator();
        out.setFloat(tvsLocal.fullScreenProgress, AnimatedFloat.VALUE, 1, TOUCH_RESPONSE_INTERPOLATOR);
        out.setFloat(tvsLocal.recentsViewScale, AnimatedFloat.VALUE, tvsLocal.getFullScreenScale(), TOUCH_RESPONSE_INTERPOLATOR);
        out.setFloat(tvsLocal.recentsViewScroll, AnimatedFloat.VALUE, 0, TOUCH_RESPONSE_INTERPOLATOR);
        out.addOnFrameCallback(() -> {
            for (RemoteTargetHandle handle : remoteTargetHandles) {
                handle.getTaskViewSimulator().apply(handle.getTransformParams());
            }
        });
        if (navBarTarget != null) {
            final Rect cropRect = new Rect();
            out.addOnFrameListener(new MultiValueUpdateListener() {

                FloatProp mNavFadeOut = new FloatProp(1f, 0f, 0, ANIMATION_NAV_FADE_OUT_DURATION, NAV_FADE_OUT_INTERPOLATOR);

                FloatProp mNavFadeIn = new FloatProp(0f, 1f, ANIMATION_DELAY_NAV_FADE_IN, ANIMATION_NAV_FADE_IN_DURATION, NAV_FADE_IN_INTERPOLATOR);

                @Override
                public void onUpdate(float percent, boolean initOnly) {
                    final SurfaceParams.Builder navBuilder = new SurfaceParams.Builder(navBarTarget.leash);
                    // TODO Do we need to operate over multiple TVSs for the navbar leash?
                    for (RemoteTargetHandle handle : remoteTargetHandles) {
                        if (mNavFadeIn.value > mNavFadeIn.getStartValue()) {
                            TaskViewSimulator taskViewSimulator = handle.getTaskViewSimulator();
                            taskViewSimulator.getCurrentCropRect().round(cropRect);
                            navBuilder.withMatrix(taskViewSimulator.getCurrentMatrix()).withWindowCrop(cropRect).withAlpha(mNavFadeIn.value);
                        } else {
                            navBuilder.withAlpha(mNavFadeOut.value);
                        }
                        handle.getTransformParams().applySurfaceParams(navBuilder.build());
                    }
                }
            });
        } else if (inLiveTileMode) {
            // There is no transition animation for app launch from recent in live tile mode so
            // we have to trigger the navigation bar animation from system here.
            final RecentsAnimationController controller = recentsView.getRecentsAnimationController();
            if (controller != null) {
                controller.animateNavigationBarToApp(RECENTS_LAUNCH_DURATION);
            }
        }
        topMostSimulators = remoteTargetHandles;
    }
    if (!skipViewChanges && parallaxCenterAndAdjacentTask && topMostSimulators.length > 0) {
        out.addFloat(v, VIEW_ALPHA, 1, 0, clampToProgress(LINEAR, 0.2f, 0.4f));
        RemoteTargetHandle[] simulatorCopies = topMostSimulators;
        for (RemoteTargetHandle handle : simulatorCopies) {
            handle.getTaskViewSimulator().apply(handle.getTransformParams());
        }
        // Mt represents the overall transformation on the thumbnailView relative to the
        // Launcher's rootView
        // K(t) represents transformation on the running window by the taskViewSimulator at
        // any time t.
        // at t = 0, we know that the simulator matches the thumbnailView. So if we apply K(0)`
        // on the Launcher's rootView, the thumbnailView would match the full running task
        // window. If we apply "K(0)` K(t)" thumbnailView will match the final transformed
        // window at any time t. This gives the overall matrix on thumbnailView to be:
        // Mt K(0)` K(t)
        // During animation we apply transformation on the thumbnailView (and not the rootView)
        // to follow the TaskViewSimulator. So the final matrix applied on the thumbnailView is:
        // Mt K(0)` K(t) Mt`
        TaskThumbnailView[] thumbnails = v.getThumbnails();
        Matrix[] mt = new Matrix[simulatorCopies.length];
        Matrix[] mti = new Matrix[simulatorCopies.length];
        for (int i = 0; i < thumbnails.length; i++) {
            TaskThumbnailView ttv = thumbnails[i];
            RectF localBounds = new RectF(0, 0, ttv.getWidth(), ttv.getHeight());
            float[] tvBoundsMapped = new float[] { 0, 0, ttv.getWidth(), ttv.getHeight() };
            getDescendantCoordRelativeToAncestor(ttv, ttv.getRootView(), tvBoundsMapped, false);
            RectF localBoundsInRoot = new RectF(tvBoundsMapped[0], tvBoundsMapped[1], tvBoundsMapped[2], tvBoundsMapped[3]);
            Matrix localMt = new Matrix();
            localMt.setRectToRect(localBounds, localBoundsInRoot, ScaleToFit.FILL);
            mt[i] = localMt;
            Matrix localMti = new Matrix();
            localMt.invert(localMti);
            mti[i] = localMti;
        }
        Matrix[] k0i = new Matrix[simulatorCopies.length];
        for (int i = 0; i < simulatorCopies.length; i++) {
            k0i[i] = new Matrix();
            simulatorCopies[i].getTaskViewSimulator().getCurrentMatrix().invert(k0i[i]);
        }
        Matrix animationMatrix = new Matrix();
        out.addOnFrameCallback(() -> {
            for (int i = 0; i < simulatorCopies.length; i++) {
                animationMatrix.set(mt[i]);
                animationMatrix.postConcat(k0i[i]);
                animationMatrix.postConcat(simulatorCopies[i].getTaskViewSimulator().getCurrentMatrix());
                animationMatrix.postConcat(mti[i]);
                thumbnails[i].setAnimationMatrix(animationMatrix);
            }
        });
        out.addListener(new AnimatorListenerAdapter() {

            @Override
            public void onAnimationEnd(Animator animation) {
                for (TaskThumbnailView ttv : thumbnails) {
                    ttv.setAnimationMatrix(null);
                }
            }
        });
    }
    out.addListener(new AnimationSuccessListener() {

        @Override
        public void onAnimationSuccess(Animator animator) {
            if (isQuickSwitch) {
                InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_QUICK_SWITCH);
            }
        }

        @Override
        public void onAnimationEnd(Animator animation) {
            targets.release();
            super.onAnimationEnd(animation);
        }
    });
    if (depthController != null) {
        out.setFloat(depthController, DEPTH, BACKGROUND_APP.getDepth(context), TOUCH_RESPONSE_INTERPOLATOR);
    }
}
Also used : DeviceProfile(com.android.launcher3.DeviceProfile) MultiValueUpdateListener(com.android.quickstep.util.MultiValueUpdateListener) SurfaceTransactionApplier(com.android.quickstep.util.SurfaceTransactionApplier) Matrix(android.graphics.Matrix) AnimatorListenerAdapter(android.animation.AnimatorListenerAdapter) SurfaceParams(com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams) AnimationSuccessListener(com.android.launcher3.anim.AnimationSuccessListener) Context(android.content.Context) Rect(android.graphics.Rect) TaskViewSimulator(com.android.quickstep.util.TaskViewSimulator) RemoteAnimationTargetCompat(com.android.systemui.shared.system.RemoteAnimationTargetCompat) RectF(android.graphics.RectF) RemoteTargetHandle(com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle) Animator(android.animation.Animator) ObjectAnimator(android.animation.ObjectAnimator) ValueAnimator(android.animation.ValueAnimator) RecentsView(com.android.quickstep.views.RecentsView) TaskThumbnailView(com.android.quickstep.views.TaskThumbnailView)

Example 13 with RemoteTargetHandle

use of com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle in project android_packages_apps_Launcher3 by ArrowOS.

the class TaskView method onClick.

private void onClick(View view) {
    if (getTask() == null) {
        return;
    }
    if (confirmSecondSplitSelectApp()) {
        return;
    }
    RecentsView recentsView = getRecentsView();
    RemoteTargetHandle[] remoteTargetHandles = recentsView.mRemoteTargetHandles;
    if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask() && remoteTargetHandles != null) {
        if (!mIsClickableAsLiveTile) {
            return;
        }
        // Reset the minimized state since we force-toggled the minimized state when entering
        // overview, but never actually finished the recents animation
        SystemUiProxy p = SystemUiProxy.INSTANCE.getNoCreate();
        if (p != null) {
            p.setSplitScreenMinimized(false);
        }
        mIsClickableAsLiveTile = false;
        RemoteAnimationTargets targets;
        if (remoteTargetHandles.length == 1) {
            targets = remoteTargetHandles[0].getTransformParams().getTargetSet();
        } else {
            TransformParams topLeftParams = remoteTargetHandles[0].getTransformParams();
            TransformParams rightBottomParams = remoteTargetHandles[1].getTransformParams();
            RemoteAnimationTargetCompat[] apps = Stream.concat(Arrays.stream(topLeftParams.getTargetSet().apps), Arrays.stream(rightBottomParams.getTargetSet().apps)).toArray(RemoteAnimationTargetCompat[]::new);
            RemoteAnimationTargetCompat[] wallpapers = Stream.concat(Arrays.stream(topLeftParams.getTargetSet().wallpapers), Arrays.stream(rightBottomParams.getTargetSet().wallpapers)).toArray(RemoteAnimationTargetCompat[]::new);
            targets = new RemoteAnimationTargets(apps, wallpapers, topLeftParams.getTargetSet().nonApps, topLeftParams.getTargetSet().targetMode);
        }
        if (targets == null) {
            // If the recents animation is cancelled somehow between the parent if block and
            // here, try to launch the task as a non live tile task.
            launchTaskAnimated();
            return;
        }
        AnimatorSet anim = new AnimatorSet();
        TaskViewUtils.composeRecentsLaunchAnimator(anim, this, targets.apps, targets.wallpapers, targets.nonApps, true, /* launcherClosing */
        mActivity.getStateManager(), recentsView, recentsView.getDepthController());
        anim.addListener(new AnimatorListenerAdapter() {

            @Override
            public void onAnimationStart(Animator animation) {
                recentsView.runActionOnRemoteHandles((Consumer<RemoteTargetHandle>) remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(false));
            }

            @Override
            public void onAnimationEnd(Animator animator) {
                mIsClickableAsLiveTile = true;
            }
        });
        anim.start();
        recentsView.onTaskLaunchedInLiveTileMode();
    } else {
        launchTaskAnimated();
    }
    mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo()).log(LAUNCHER_TASK_LAUNCH_TAP);
}
Also used : RemoteAnimationTargetCompat(com.android.systemui.shared.system.RemoteAnimationTargetCompat) RemoteAnimationTargets(com.android.quickstep.RemoteAnimationTargets) AnimatorSet(android.animation.AnimatorSet) RemoteTargetHandle(com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle) Animator(android.animation.Animator) ObjectAnimator(android.animation.ObjectAnimator) Consumer(java.util.function.Consumer) AnimatorListenerAdapter(android.animation.AnimatorListenerAdapter) TransformParams(com.android.quickstep.util.TransformParams) SystemUiProxy(com.android.quickstep.SystemUiProxy)

Example 14 with RemoteTargetHandle

use of com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle in project android_packages_apps_Launcher3 by ProtonAOSP.

the class AbsSwipeUpHandler method applyScrollAndTransform.

/**
 * Applies the transform on the recents animation
 */
protected void applyScrollAndTransform() {
    // No need to apply any transform if there is ongoing swipe-pip-to-home animator since
    // that animator handles the leash solely.
    boolean notSwipingPipToHome = mRecentsAnimationTargets != null && !mIsSwipingPipToHome;
    boolean setRecentsScroll = mRecentsViewScrollLinked && mRecentsView != null;
    for (RemoteTargetHandle remoteHandle : mRemoteTargetHandles) {
        AnimatorControllerWithResistance playbackController = remoteHandle.getPlaybackController();
        if (playbackController != null) {
            playbackController.setProgress(Math.max(mCurrentShift.value, getScaleProgressDueToScroll()), mDragLengthFactor);
        }
        if (notSwipingPipToHome) {
            TaskViewSimulator taskViewSimulator = remoteHandle.getTaskViewSimulator();
            if (setRecentsScroll) {
                taskViewSimulator.setScroll(mRecentsView.getScrollOffset());
            }
            taskViewSimulator.apply(remoteHandle.getTransformParams());
        }
    }
    ProtoTracer.INSTANCE.get(mContext).scheduleFrameUpdate();
}
Also used : RemoteTargetHandle(com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle) TaskViewSimulator(com.android.quickstep.util.TaskViewSimulator) AnimatorControllerWithResistance(com.android.quickstep.util.AnimatorControllerWithResistance)

Example 15 with RemoteTargetHandle

use of com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle in project android_packages_apps_Launcher3 by ProtonAOSP.

the class RecentsView method createTaskDismissAnimation.

/**
 * Creates a {@link PendingAnimation} for dismissing the specified {@link TaskView}.
 * @param dismissedTaskView the {@link TaskView} to be dismissed
 * @param animateTaskView whether the {@link TaskView} to be dismissed should be animated
 * @param shouldRemoveTask whether the associated {@link Task} should be removed from
 *                         ActivityManager after dismissal
 * @param duration duration of the animation
 * @param dismissingForSplitSelection task dismiss animation is used for entering split
 *                                    selection state from app icon
 */
public PendingAnimation createTaskDismissAnimation(TaskView dismissedTaskView, boolean animateTaskView, boolean shouldRemoveTask, long duration, boolean dismissingForSplitSelection) {
    if (mPendingAnimation != null) {
        mPendingAnimation.createPlaybackController().dispatchOnCancel().dispatchOnEnd();
    }
    PendingAnimation anim = new PendingAnimation(duration);
    int count = getPageCount();
    if (count == 0) {
        return anim;
    }
    boolean showAsGrid = showAsGrid();
    int taskCount = getTaskViewCount();
    int dismissedIndex = indexOfChild(dismissedTaskView);
    int dismissedTaskViewId = dismissedTaskView.getTaskViewId();
    // Grid specific properties.
    boolean isFocusedTaskDismissed = false;
    TaskView nextFocusedTaskView = null;
    boolean nextFocusedTaskFromTop = false;
    float dismissedTaskWidth = 0;
    float nextFocusedTaskWidth = 0;
    // Non-grid specific properties.
    int[] oldScroll = new int[count];
    int[] newScroll = new int[count];
    int scrollDiffPerPage = 0;
    boolean needsCurveUpdates = false;
    if (showAsGrid) {
        dismissedTaskWidth = dismissedTaskView.getLayoutParams().width + mPageSpacing;
        isFocusedTaskDismissed = dismissedTaskViewId == mFocusedTaskViewId;
        if (isFocusedTaskDismissed && !isSplitSelectionActive()) {
            nextFocusedTaskFromTop = mTopRowIdSet.size() > 0 && mTopRowIdSet.size() >= (taskCount - 1) / 2f;
            // Pick the next focused task from the preferred row.
            for (int i = 0; i < taskCount; i++) {
                TaskView taskView = requireTaskViewAt(i);
                if (taskView == dismissedTaskView) {
                    continue;
                }
                boolean isTopRow = mTopRowIdSet.contains(taskView.getTaskViewId());
                if ((nextFocusedTaskFromTop && isTopRow || (!nextFocusedTaskFromTop && !isTopRow))) {
                    nextFocusedTaskView = taskView;
                    break;
                }
            }
            if (nextFocusedTaskView != null) {
                nextFocusedTaskWidth = nextFocusedTaskView.getLayoutParams().width + mPageSpacing;
            }
        }
    } else {
        getPageScrolls(oldScroll, false, SIMPLE_SCROLL_LOGIC);
        getPageScrolls(newScroll, false, v -> v.getVisibility() != GONE && v != dismissedTaskView);
        if (count > 1) {
            scrollDiffPerPage = Math.abs(oldScroll[1] - oldScroll[0]);
        }
    }
    announceForAccessibility(getResources().getString(R.string.task_view_closed));
    float dismissTranslationInterpolationEnd = 1;
    boolean closeGapBetweenClearAll = false;
    boolean isClearAllHidden = isClearAllHidden();
    boolean snapToLastTask = false;
    boolean isLandscapeSplit = mActivity.getDeviceProfile().isLandscape && isSplitSelectionActive();
    boolean isSplitPlaceholderFirstInGrid = isSplitPlaceholderFirstInGrid();
    boolean isSplitPlaceholderLastInGrid = isSplitPlaceholderLastInGrid();
    TaskView lastGridTaskView = showAsGrid ? getLastGridTaskView() : null;
    int currentPageScroll = getScrollForPage(mCurrentPage);
    int lastGridTaskScroll = getScrollForPage(indexOfChild(lastGridTaskView));
    boolean currentPageSnapsToEndOfGrid = currentPageScroll == lastGridTaskScroll;
    if (lastGridTaskView != null && lastGridTaskView.isVisibleToUser()) {
        // After dismissal, animate translation of the remaining tasks to fill any gap left
        // between the end of the grid and the clear all button. Only animate if the clear
        // all button is visible or would become visible after dismissal.
        float longGridRowWidthDiff = 0;
        int topGridRowSize = mTopRowIdSet.size();
        int bottomGridRowSize = taskCount - mTopRowIdSet.size() - 1;
        boolean topRowLonger = topGridRowSize > bottomGridRowSize;
        boolean bottomRowLonger = bottomGridRowSize > topGridRowSize;
        boolean dismissedTaskFromTop = mTopRowIdSet.contains(dismissedTaskViewId);
        boolean dismissedTaskFromBottom = !dismissedTaskFromTop && !isFocusedTaskDismissed;
        float gapWidth = 0;
        if ((topRowLonger && dismissedTaskFromTop) || (bottomRowLonger && dismissedTaskFromBottom)) {
            gapWidth = dismissedTaskWidth;
        } else if ((topRowLonger && nextFocusedTaskFromTop) || (bottomRowLonger && !nextFocusedTaskFromTop)) {
            gapWidth = nextFocusedTaskWidth;
        }
        if (gapWidth > 0) {
            if (taskCount > 2) {
                // Compensate the removed gap.
                longGridRowWidthDiff += mIsRtl ? -gapWidth : gapWidth;
                if (isClearAllHidden) {
                    // If ClearAllButton isn't fully shown, snap to the last task.
                    snapToLastTask = true;
                }
            } else {
                // If only focused task will be left, snap to focused task instead.
                longGridRowWidthDiff += getSnapToFocusedTaskScrollDiff(isClearAllHidden);
            }
        }
        if (mClearAllButton.getAlpha() != 0f && isLandscapeSplit) {
            // ClearAllButton will not be available in split select, snap to last task instead.
            snapToLastTask = true;
        }
        if (snapToLastTask) {
            longGridRowWidthDiff += getSnapToLastTaskScrollDiff();
            if (isSplitPlaceholderLastInGrid) {
                // Shift all the tasks to make space for split placeholder.
                longGridRowWidthDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
            }
        } else if (isLandscapeSplit && currentPageSnapsToEndOfGrid) {
            // Use last task as reference point for scroll diff and snapping calculation as it's
            // the only invariant point in landscape split screen.
            snapToLastTask = true;
        }
        // fake it using interpolation.
        if (longGridRowWidthDiff != 0) {
            closeGapBetweenClearAll = true;
            // Stagger the offsets of each additional task for a delayed animation. We use
            // half here as this animation is half of half of an animation (1/4th).
            float halfAdditionalDismissTranslationOffset = (0.5f * ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET);
            dismissTranslationInterpolationEnd = Utilities.boundToRange(END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + (taskCount - 1) * halfAdditionalDismissTranslationOffset, END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET, 1);
            for (int i = 0; i < taskCount; i++) {
                TaskView taskView = requireTaskViewAt(i);
                anim.setFloat(taskView, TaskView.GRID_END_TRANSLATION_X, longGridRowWidthDiff, clampToProgress(LINEAR, dismissTranslationInterpolationEnd, 1));
                dismissTranslationInterpolationEnd = Utilities.boundToRange(dismissTranslationInterpolationEnd - halfAdditionalDismissTranslationOffset, END_DISMISS_TRANSLATION_INTERPOLATION_OFFSET, 1);
                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && taskView.isRunningTask()) {
                    anim.addOnFrameCallback(() -> {
                        runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().taskPrimaryTranslation.value = TaskView.GRID_END_TRANSLATION_X.get(taskView));
                        redrawLiveTile();
                    });
                }
            }
            // Change alpha of clear all if translating grid to hide it
            if (isClearAllHidden) {
                anim.setFloat(mClearAllButton, DISMISS_ALPHA, 0, LINEAR);
                anim.addListener(new AnimatorListenerAdapter() {

                    @Override
                    public void onAnimationEnd(Animator animation) {
                        super.onAnimationEnd(animation);
                        mClearAllButton.setDismissAlpha(1);
                    }
                });
            }
        }
    }
    int distanceFromDismissedTask = 0;
    for (int i = 0; i < count; i++) {
        View child = getChildAt(i);
        if (child == dismissedTaskView) {
            if (animateTaskView) {
                if (dismissingForSplitSelection) {
                    createInitialSplitSelectAnimation(anim);
                } else {
                    addDismissedTaskAnimations(dismissedTaskView, duration, anim);
                }
            }
        } else if (!showAsGrid) {
            // Compute scroll offsets from task dismissal for animation.
            // If we just take newScroll - oldScroll, everything to the right of dragged task
            // translates to the left. We need to offset this in some cases:
            // - In RTL, add page offset to all pages, since we want pages to move to the right
            // Additionally, add a page offset if:
            // - Current page is rightmost page (leftmost for RTL)
            // - Dragging an adjacent page on the left side (right side for RTL)
            int offset = mIsRtl ? scrollDiffPerPage : 0;
            if (mCurrentPage == dismissedIndex) {
                int lastPage = taskCount - 1;
                if (mCurrentPage == lastPage) {
                    offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
                }
            } else {
                // Dismissing an adjacent page.
                // (Right in RTL, left in LTR)
                int negativeAdjacent = mCurrentPage - 1;
                if (dismissedIndex == negativeAdjacent) {
                    offset += mIsRtl ? -scrollDiffPerPage : scrollDiffPerPage;
                }
            }
            int scrollDiff = newScroll[i] - oldScroll[i] + offset;
            if (scrollDiff != 0) {
                FloatProperty translationProperty = child instanceof TaskView ? ((TaskView) child).getPrimaryDismissTranslationProperty() : mOrientationHandler.getPrimaryViewTranslate();
                float additionalDismissDuration = ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * Math.abs(i - dismissedIndex);
                anim.setFloat(child, translationProperty, scrollDiff, clampToProgress(LINEAR, Utilities.boundToRange(INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + additionalDismissDuration, 0f, 1f), 1));
                if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && child instanceof TaskView && ((TaskView) child).isRunningTask()) {
                    anim.addOnFrameCallback(() -> {
                        runActionOnRemoteHandles(remoteTargetHandle -> remoteTargetHandle.getTaskViewSimulator().taskPrimaryTranslation.value = mOrientationHandler.getPrimaryValue(child.getTranslationX(), child.getTranslationY()));
                        redrawLiveTile();
                    });
                }
                needsCurveUpdates = true;
            }
        } else if (child instanceof TaskView) {
            TaskView taskView = (TaskView) child;
            if (isFocusedTaskDismissed) {
                if (nextFocusedTaskView != null && !isSameGridRow(taskView, nextFocusedTaskView)) {
                    continue;
                }
            } else {
                if (i < dismissedIndex || !isSameGridRow(taskView, dismissedTaskView)) {
                    continue;
                }
            }
            // Animate task with index >= dismissed index and in the same row as the
            // dismissed index or next focused index. Offset successive task dismissal
            // durations for a staggered effect.
            float animationStartProgress = Utilities.boundToRange(INITIAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET + ADDITIONAL_DISMISS_TRANSLATION_INTERPOLATION_OFFSET * ++distanceFromDismissedTask, 0f, dismissTranslationInterpolationEnd);
            if (taskView == nextFocusedTaskView) {
                // Enlarge the task to be focused next, and translate into focus position.
                float scale = mTaskWidth / (float) mLastComputedGridTaskSize.width();
                anim.setFloat(taskView, TaskView.SNAPSHOT_SCALE, scale, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), mIsRtl ? dismissedTaskWidth : -dismissedTaskWidth, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                float secondaryTranslation = -mTaskGridVerticalDiff;
                if (!nextFocusedTaskFromTop) {
                    secondaryTranslation -= mTopBottomRowHeightDiff;
                }
                anim.setFloat(taskView, taskView.getSecondaryDissmissTranslationProperty(), secondaryTranslation, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
                anim.setFloat(taskView, TaskView.FOCUS_TRANSITION, 0f, clampToProgress(LINEAR, 0f, ANIMATION_DISMISS_PROGRESS_MIDPOINT));
            } else {
                float primaryTranslation = nextFocusedTaskView != null ? nextFocusedTaskWidth : dismissedTaskWidth;
                if (isFocusedTaskDismissed && nextFocusedTaskView == null) {
                    // Moves less if focused task is not in scroll position.
                    int focusedTaskScroll = getScrollForPage(dismissedIndex);
                    int primaryScroll = mOrientationHandler.getPrimaryScroll(this);
                    int focusedTaskScrollDiff = primaryScroll - focusedTaskScroll;
                    primaryTranslation += mIsRtl ? focusedTaskScrollDiff : -focusedTaskScrollDiff;
                    if (isSplitPlaceholderFirstInGrid) {
                        // Moves less if split placeholder is at the start.
                        primaryTranslation += mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
                    }
                }
                anim.setFloat(taskView, taskView.getPrimaryDismissTranslationProperty(), mIsRtl ? primaryTranslation : -primaryTranslation, clampToProgress(LINEAR, animationStartProgress, dismissTranslationInterpolationEnd));
            }
        }
    }
    if (needsCurveUpdates) {
        anim.addOnFrameCallback(this::updateCurveProperties);
    }
    // Add a tiny bit of translation Z, so that it draws on top of other views
    if (animateTaskView) {
        dismissedTaskView.setTranslationZ(0.1f);
    }
    mPendingAnimation = anim;
    final TaskView finalNextFocusedTaskView = nextFocusedTaskView;
    final boolean finalCloseGapBetweenClearAll = closeGapBetweenClearAll;
    final boolean finalSnapToLastTask = snapToLastTask;
    final boolean finalIsFocusedTaskDismissed = isFocusedTaskDismissed;
    mPendingAnimation.addEndListener(new Consumer<Boolean>() {

        @Override
        public void accept(Boolean success) {
            if (ENABLE_QUICKSTEP_LIVE_TILE.get() && mEnableDrawingLiveTile && dismissedTaskView.isRunningTask() && success) {
                finishRecentsAnimation(true, /* toRecents */
                false, /* shouldPip */
                () -> onEnd(success));
            } else {
                onEnd(success);
            }
        }

        @SuppressWarnings("WrongCall")
        private void onEnd(boolean success) {
            // Reset task translations as they may have updated via animations in
            // createTaskDismissAnimation
            resetTaskVisuals();
            if (success) {
                if (shouldRemoveTask) {
                    if (dismissedTaskView.getTask() != null) {
                        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && dismissedTaskView.isRunningTask()) {
                            finishRecentsAnimation(true, /* toRecents */
                            false, /* shouldPip */
                            () -> removeTaskInternal(dismissedTaskViewId));
                        } else {
                            removeTaskInternal(dismissedTaskViewId);
                        }
                        mActivity.getStatsLogManager().logger().withItemInfo(dismissedTaskView.getItemInfo()).log(LAUNCHER_TASK_DISMISS_SWIPE_UP);
                    }
                }
                int pageToSnapTo = mCurrentPage;
                mCurrentPageScrollDiff = 0;
                int taskViewIdToSnapTo = -1;
                if (showAsGrid) {
                    if (finalCloseGapBetweenClearAll) {
                        if (finalSnapToLastTask) {
                            // Last task will be determined after removing dismissed task.
                            pageToSnapTo = -1;
                        } else if (taskCount > 2) {
                            pageToSnapTo = indexOfChild(mClearAllButton);
                        } else if (isClearAllHidden) {
                            // Snap to focused task if clear all is hidden.
                            pageToSnapTo = 0;
                        }
                    } else {
                        // Get the id of the task view we will snap to based on the current
                        // page's relative position as the order of indices change over time due
                        // to dismissals.
                        TaskView snappedTaskView = getTaskViewAt(mCurrentPage);
                        boolean calculateScrollDiff = true;
                        if (snappedTaskView != null && !finalSnapToLastTask) {
                            if (snappedTaskView.getTaskViewId() == mFocusedTaskViewId) {
                                if (finalNextFocusedTaskView != null) {
                                    taskViewIdToSnapTo = finalNextFocusedTaskView.getTaskViewId();
                                } else if (dismissedTaskViewId != mFocusedTaskViewId) {
                                    taskViewIdToSnapTo = mFocusedTaskViewId;
                                } else {
                                    // Won't focus next task in split select, so snap to the
                                    // first task.
                                    pageToSnapTo = 0;
                                    calculateScrollDiff = false;
                                }
                            } else {
                                int snappedTaskViewId = snappedTaskView.getTaskViewId();
                                boolean isSnappedTaskInTopRow = mTopRowIdSet.contains(snappedTaskViewId);
                                IntArray taskViewIdArray = isSnappedTaskInTopRow ? getTopRowIdArray() : getBottomRowIdArray();
                                int snappedIndex = taskViewIdArray.indexOf(snappedTaskViewId);
                                taskViewIdArray.removeValue(dismissedTaskViewId);
                                if (finalNextFocusedTaskView != null) {
                                    taskViewIdArray.removeValue(finalNextFocusedTaskView.getTaskViewId());
                                }
                                if (snappedIndex < taskViewIdArray.size()) {
                                    taskViewIdToSnapTo = taskViewIdArray.get(snappedIndex);
                                } else if (snappedIndex == taskViewIdArray.size()) {
                                    // If the snapped task is the last item from the
                                    // dismissed row,
                                    // snap to the same column in the other grid row
                                    IntArray inverseRowTaskViewIdArray = isSnappedTaskInTopRow ? getBottomRowIdArray() : getTopRowIdArray();
                                    if (snappedIndex < inverseRowTaskViewIdArray.size()) {
                                        taskViewIdToSnapTo = inverseRowTaskViewIdArray.get(snappedIndex);
                                    }
                                }
                            }
                        }
                        if (calculateScrollDiff) {
                            int primaryScroll = mOrientationHandler.getPrimaryScroll(RecentsView.this);
                            int currentPageScroll = getScrollForPage(mCurrentPage);
                            mCurrentPageScrollDiff = primaryScroll - currentPageScroll;
                            // Compensate for coordinate shift by split placeholder.
                            if (isSplitPlaceholderFirstInGrid && !finalSnapToLastTask) {
                                mCurrentPageScrollDiff += mIsRtl ? -mSplitPlaceholderSize : mSplitPlaceholderSize;
                            } else if (isSplitPlaceholderLastInGrid && finalSnapToLastTask) {
                                mCurrentPageScrollDiff += mIsRtl ? mSplitPlaceholderSize : -mSplitPlaceholderSize;
                            }
                        }
                    }
                } else if (dismissedIndex < pageToSnapTo || pageToSnapTo == taskCount - 1) {
                    pageToSnapTo--;
                }
                boolean isHomeTaskDismissed = dismissedTaskView == getHomeTaskView();
                removeViewInLayout(dismissedTaskView);
                mTopRowIdSet.remove(dismissedTaskViewId);
                if (taskCount == 1) {
                    removeViewInLayout(mClearAllButton);
                    if (isHomeTaskDismissed) {
                        updateEmptyMessage();
                    } else {
                        startHome();
                    }
                } else {
                    // Update focus task and its size.
                    if (finalIsFocusedTaskDismissed && finalNextFocusedTaskView != null) {
                        mFocusedTaskViewId = finalNextFocusedTaskView.getTaskViewId();
                        mTopRowIdSet.remove(mFocusedTaskViewId);
                        finalNextFocusedTaskView.animateIconScaleAndDimIntoView();
                    }
                    updateTaskSize(/*isTaskDismissal=*/
                    true);
                    updateChildTaskOrientations();
                    // Update scroll and snap to page.
                    updateScrollSynchronously();
                    if (showAsGrid) {
                        // Rebalance tasks in the grid
                        int highestVisibleTaskIndex = getHighestVisibleTaskIndex();
                        if (highestVisibleTaskIndex < Integer.MAX_VALUE) {
                            TaskView taskView = requireTaskViewAt(highestVisibleTaskIndex);
                            boolean shouldRebalance;
                            int screenStart = mOrientationHandler.getPrimaryScroll(RecentsView.this);
                            int taskStart = mOrientationHandler.getChildStart(taskView) + (int) taskView.getOffsetAdjustment(/*fullscreenEnabled=*/
                            false, /*gridEnabled=*/
                            true);
                            // visible screen.
                            if (mIsRtl) {
                                shouldRebalance = taskStart <= screenStart + mPageSpacing;
                            } else {
                                int screenEnd = screenStart + mOrientationHandler.getMeasuredSize(RecentsView.this);
                                int taskSize = (int) (mOrientationHandler.getMeasuredSize(taskView) * taskView.getSizeAdjustment(/*fullscreenEnabled=*/
                                false));
                                int taskEnd = taskStart + taskSize;
                                shouldRebalance = taskEnd >= screenEnd - mPageSpacing;
                            }
                            if (shouldRebalance) {
                                updateGridProperties(/*isTaskDismissal=*/
                                true, highestVisibleTaskIndex);
                                updateScrollSynchronously();
                            }
                        }
                        IntArray topRowIdArray = getTopRowIdArray();
                        IntArray bottomRowIdArray = getBottomRowIdArray();
                        if (finalSnapToLastTask) {
                            // If snapping to last task, find the last task after dismissal.
                            pageToSnapTo = indexOfChild(getLastGridTaskView(topRowIdArray, bottomRowIdArray));
                        } else if (taskViewIdToSnapTo != -1) {
                            // If snapping to another page due to indices rearranging, find
                            // the new index after dismissal & rearrange using the task view id.
                            pageToSnapTo = indexOfChild(getTaskViewFromTaskViewId(taskViewIdToSnapTo));
                            if (!currentPageSnapsToEndOfGrid) {
                                // If it wasn't snapped to one of the last pages, but is now
                                // snapped to last pages, we'll need to compensate for the
                                // offset from the page's scroll to its visual position.
                                mCurrentPageScrollDiff += getOffsetFromScrollPosition(pageToSnapTo, topRowIdArray, bottomRowIdArray);
                            }
                        }
                    }
                    pageBeginTransition();
                    setCurrentPage(pageToSnapTo);
                    // Update various scroll-dependent UI.
                    dispatchScrollChanged();
                    updateActionsViewFocusedScroll();
                    if (isClearAllHidden()) {
                        mActionsView.updateDisabledFlags(OverviewActionsView.DISABLED_SCROLLING, false);
                    }
                }
            }
            updateCurrentTaskActionsVisibility();
            onDismissAnimationEnds();
            mPendingAnimation = null;
        }
    });
    return anim;
}
Also used : BACKGROUND_APP(com.android.launcher3.LauncherState.BACKGROUND_APP) RemoteTargetGluer(com.android.quickstep.RemoteTargetGluer) HIDDEN_NO_TASKS(com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS) Bundle(android.os.Bundle) Overrides(com.android.launcher3.util.ResourceBasedOverride.Overrides) NonNull(androidx.annotation.NonNull) AnimatorListeners(com.android.launcher3.anim.AnimatorListeners) AccessibilityManagerCompat(com.android.launcher3.compat.AccessibilityManagerCompat) BaseActivityInterface(com.android.quickstep.BaseActivityInterface) Drawable(android.graphics.drawable.Drawable) TaskViewSimulator(com.android.quickstep.util.TaskViewSimulator) LayoutTransition(android.animation.LayoutTransition) PropertyValuesHolder(android.animation.PropertyValuesHolder) TaskStackChangeListeners(com.android.systemui.shared.system.TaskStackChangeListeners) UiThread(androidx.annotation.UiThread) Canvas(android.graphics.Canvas) LayoutUtils(com.android.quickstep.util.LayoutUtils) AccessibilityEvent(android.view.accessibility.AccessibilityEvent) TargetApi(android.annotation.TargetApi) Log(android.util.Log) TaskVisualsChangeListener(com.android.quickstep.RecentsModel.TaskVisualsChangeListener) RecentsAnimationTargets(com.android.quickstep.RecentsAnimationTargets) HIDDEN_NO_RECENTS(com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS) Interpolator(android.view.animation.Interpolator) HIDDEN_NON_ZERO_ROTATION(com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION) AnimatorListenerAdapter(android.animation.AnimatorListenerAdapter) DeviceProfile(com.android.launcher3.DeviceProfile) HapticFeedbackConstants(android.view.HapticFeedbackConstants) LAUNCHER_TASK_LAUNCH_SWIPE_DOWN(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_SWIPE_DOWN) Nullable(androidx.annotation.Nullable) UI_STATE_FULLSCREEN_TASK(com.android.launcher3.util.SystemUiController.UI_STATE_FULLSCREEN_TASK) Layout(android.text.Layout) MultiWindowModeChangedListener(com.android.launcher3.BaseActivity.MultiWindowModeChangedListener) TextPaint(android.text.TextPaint) AbstractFloatingView.getTopOpenViewWithType(com.android.launcher3.AbstractFloatingView.getTopOpenViewWithType) RemoteAnimationTargetCompat(com.android.systemui.shared.system.RemoteAnimationTargetCompat) TaskKey(com.android.systemui.shared.recents.model.Task.TaskKey) Insettable(com.android.launcher3.Insettable) SystemClock(android.os.SystemClock) Utilities.squaredTouchSlop(com.android.launcher3.Utilities.squaredTouchSlop) SystemUiProxy(com.android.quickstep.SystemUiProxy) CANVAS_TRANSLATE(com.android.launcher3.touch.PagedOrientationHandler.CANVAS_TRANSLATE) RemoteAnimationTargets(com.android.quickstep.RemoteAnimationTargets) ArrayList(java.util.ArrayList) TransformParams(com.android.quickstep.util.TransformParams) TaskUtils.checkCurrentOrManagedUserId(com.android.quickstep.TaskUtils.checkCurrentOrManagedUserId) SplitScreenBounds(com.android.quickstep.util.SplitScreenBounds) VibrationEffect(android.os.VibrationEffect) UserHandle(android.os.UserHandle) Toast(android.widget.Toast) Utilities.mapToRange(com.android.launcher3.Utilities.mapToRange) DEPTH(com.android.launcher3.statehandlers.DepthController.DEPTH) LocusId(android.content.LocusId) IntArray(com.android.launcher3.util.IntArray) MeasureSpec.makeMeasureSpec(android.view.View.MeasureSpec.makeMeasureSpec) DISMISS_ALPHA(com.android.quickstep.views.ClearAllButton.DISMISS_ALPHA) BaseState(com.android.launcher3.statemanager.BaseState) SpringProperty(com.android.launcher3.anim.SpringProperty) OverScroll(com.android.launcher3.touch.OverScroll) ViewPool(com.android.launcher3.util.ViewPool) ViewDebug(android.view.ViewDebug) FeatureFlags(com.android.launcher3.config.FeatureFlags) DynamicResource(com.android.launcher3.util.DynamicResource) SUCCESS_TRANSITION_PROGRESS(com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS) LINEAR(com.android.launcher3.anim.Interpolators.LINEAR) IntSet(com.android.launcher3.util.IntSet) SparseBooleanArray(android.util.SparseBooleanArray) HandlerRunnable(com.android.launcher3.icons.cache.HandlerRunnable) R(com.android.launcher3.R) TranslateEdgeEffect(com.android.launcher3.util.TranslateEdgeEffect) Configuration(android.content.res.Configuration) ColorUtils(androidx.core.graphics.ColorUtils) RunnableList(com.android.launcher3.util.RunnableList) ACCEL(com.android.launcher3.anim.Interpolators.ACCEL) ValueAnimator(android.animation.ValueAnimator) Rect(android.graphics.Rect) PackageManagerWrapper(com.android.systemui.shared.system.PackageManagerWrapper) PointF(android.graphics.PointF) StagedSplitBounds(com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds) Task(com.android.systemui.shared.recents.model.Task) Interpolators.clampToProgress(com.android.launcher3.anim.Interpolators.clampToProgress) RECENTS_LAUNCH_DURATION(com.android.launcher3.QuickstepTransitionManager.RECENTS_LAUNCH_DURATION) Animator(android.animation.Animator) STAGE_POSITION_TOP_OR_LEFT(com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) FloatProperty(android.util.FloatProperty) AttributeSet(android.util.AttributeSet) ActivityManagerWrapper(com.android.systemui.shared.system.ActivityManagerWrapper) TaskViewUtils(com.android.quickstep.TaskViewUtils) STAGE_POSITION_BOTTOM_OR_RIGHT(com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT) MAIN_EXECUTOR(com.android.launcher3.util.Executors.MAIN_EXECUTOR) View(android.view.View) VibratorWrapper(com.android.quickstep.util.VibratorWrapper) Matrix(android.graphics.Matrix) RectF(android.graphics.RectF) OverScroller(android.widget.OverScroller) Utilities(com.android.launcher3.Utilities) AnimatedFloat(com.android.quickstep.AnimatedFloat) TransitionListener(android.animation.LayoutTransition.TransitionListener) UI_HELPER_EXECUTOR(com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR) DepthController(com.android.launcher3.statehandlers.DepthController) ObjectAnimator(android.animation.ObjectAnimator) EDGE_NAV_BAR(com.android.launcher3.Utilities.EDGE_NAV_BAR) TaskStackChangeListener(com.android.systemui.shared.system.TaskStackChangeListener) ROTATION_0(android.view.Surface.ROTATION_0) ViewGroup(android.view.ViewGroup) MultiValueAlpha(com.android.launcher3.util.MultiValueAlpha) SplitSelectStateController(com.android.quickstep.util.SplitSelectStateController) Objects(java.util.Objects) List(java.util.List) OnScrollChangedListener(android.view.ViewTreeObserver.OnScrollChangedListener) HIDDEN_SPLIT_SCREEN(com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN) ThumbnailData(com.android.systemui.shared.recents.model.ThumbnailData) RemoteTargetHandle(com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle) ListView(android.widget.ListView) Themes(com.android.launcher3.util.Themes) SurfaceTransactionApplier(com.android.quickstep.util.SurfaceTransactionApplier) TYPE_TASK_MENU(com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU) IPipAnimationListener(com.android.wm.shell.pip.IPipAnimationListener) ACCEL_DEACCEL(com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL) Typeface(android.graphics.Typeface) Context(android.content.Context) StaticLayout(android.text.StaticLayout) AccessibilityNodeInfo(android.view.accessibility.AccessibilityNodeInfo) TaskThumbnailCache(com.android.quickstep.TaskThumbnailCache) KeyEvent(android.view.KeyEvent) LAUNCHER_TASK_CLEAR_ALL(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_CLEAR_ALL) RunningTaskInfo(android.app.ActivityManager.RunningTaskInfo) EXACTLY(android.view.View.MeasureSpec.EXACTLY) STATE_HANDLER_INVISIBILITY_FLAGS(com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS) Pair(android.util.Pair) LAUNCHER_TASK_DISMISS_SWIPE_UP(com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_DISMISS_SWIPE_UP) HashMap(java.util.HashMap) FAST_OUT_SLOW_IN(com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN) AnimatorPlaybackController(com.android.launcher3.anim.AnimatorPlaybackController) Utilities.squaredHypot(com.android.launcher3.Utilities.squaredHypot) ENABLE_QUICKSTEP_LIVE_TILE(com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE) MotionEvent(android.view.MotionEvent) BaseActivity(com.android.launcher3.BaseActivity) AnimatorSet(android.animation.AnimatorSet) Build(android.os.Build) TaskOverlayFactory(com.android.quickstep.TaskOverlayFactory) SurfaceParams(com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams) GroupTask(com.android.quickstep.util.GroupTask) LayoutInflater(android.view.LayoutInflater) GestureState(com.android.quickstep.GestureState) RecentsAnimationController(com.android.quickstep.RecentsAnimationController) TASK_VIEW_ID_CRASH(com.android.launcher3.testing.TestProtocol.TASK_VIEW_ID_CRASH) StatefulActivity(com.android.launcher3.statemanager.StatefulActivity) Point(android.graphics.Point) RecentsOrientedState(com.android.quickstep.util.RecentsOrientedState) ResourceProvider(com.android.systemui.plugins.ResourceProvider) VIEW_ALPHA(com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA) BlendMode(android.graphics.BlendMode) Color(android.graphics.Color) Consumer(java.util.function.Consumer) InvariantDeviceProfile(com.android.launcher3.InvariantDeviceProfile) FINAL_FRAME(com.android.launcher3.anim.Interpolators.FINAL_FRAME) RecentsModel(com.android.quickstep.RecentsModel) PagedView(com.android.launcher3.PagedView) ACCEL_0_75(com.android.launcher3.anim.Interpolators.ACCEL_0_75) PagedOrientationHandler(com.android.launcher3.touch.PagedOrientationHandler) StagePosition(com.android.launcher3.util.SplitConfigurationOptions.StagePosition) PendingAnimation(com.android.launcher3.anim.PendingAnimation) ViewUtils(com.android.quickstep.ViewUtils) PendingAnimation(com.android.launcher3.anim.PendingAnimation) View(android.view.View) ListView(android.widget.ListView) PagedView(com.android.launcher3.PagedView) TextPaint(android.text.TextPaint) Point(android.graphics.Point) ValueAnimator(android.animation.ValueAnimator) Animator(android.animation.Animator) ObjectAnimator(android.animation.ObjectAnimator) IntArray(com.android.launcher3.util.IntArray) AnimatorListenerAdapter(android.animation.AnimatorListenerAdapter) FloatProperty(android.util.FloatProperty)

Aggregations

RemoteTargetHandle (com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle)32 TaskViewSimulator (com.android.quickstep.util.TaskViewSimulator)20 Matrix (android.graphics.Matrix)16 RectF (android.graphics.RectF)16 Animator (android.animation.Animator)12 AnimatorListenerAdapter (android.animation.AnimatorListenerAdapter)12 AnimatorSet (android.animation.AnimatorSet)12 ObjectAnimator (android.animation.ObjectAnimator)12 RemoteAnimationTargetCompat (com.android.systemui.shared.system.RemoteAnimationTargetCompat)12 PropertyValuesHolder (android.animation.PropertyValuesHolder)8 ValueAnimator (android.animation.ValueAnimator)8 Context (android.content.Context)8 Point (android.graphics.Point)8 Rect (android.graphics.Rect)8 TextPaint (android.text.TextPaint)8 DeviceProfile (com.android.launcher3.DeviceProfile)8 AnimatorPlaybackController (com.android.launcher3.anim.AnimatorPlaybackController)8 PendingAnimation (com.android.launcher3.anim.PendingAnimation)8 RemoteAnimationTargets (com.android.quickstep.RemoteAnimationTargets)8 SystemUiProxy (com.android.quickstep.SystemUiProxy)8