/*
 * Copyright (C) 2014 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.systemui.recents.views;

import static android.app.ActivityManager.StackId.FREEFORM_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.FULLSCREEN_WORKSPACE_STACK_ID;
import static android.app.ActivityManager.StackId.INVALID_STACK_ID;

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.ComponentName;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.GradientDrawable;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.Settings;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.MutableBoolean;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewDebug;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.FrameLayout;

import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.MetricsProto.MetricsEvent;
import com.android.systemui.Interpolators;
import com.android.systemui.R;
import com.android.systemui.recents.Recents;
import com.android.systemui.recents.RecentsActivity;
import com.android.systemui.recents.RecentsActivityLaunchState;
import com.android.systemui.recents.RecentsConfiguration;
import com.android.systemui.recents.RecentsDebugFlags;
import com.android.systemui.recents.events.EventBus;
import com.android.systemui.recents.events.activity.CancelEnterRecentsWindowAnimationEvent;
import com.android.systemui.recents.events.activity.ConfigurationChangedEvent;
import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
import com.android.systemui.recents.events.activity.EnterRecentsTaskStackAnimationCompletedEvent;
import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
import com.android.systemui.recents.events.activity.HideHistoryButtonEvent;
import com.android.systemui.recents.events.activity.HideHistoryEvent;
import com.android.systemui.recents.events.activity.IterateRecentsEvent;
import com.android.systemui.recents.events.activity.LaunchNextTaskRequestEvent;
import com.android.systemui.recents.events.activity.LaunchTaskEvent;
import com.android.systemui.recents.events.activity.LaunchTaskStartedEvent;
import com.android.systemui.recents.events.activity.MultiWindowStateChangedEvent;
import com.android.systemui.recents.events.activity.PackagesChangedEvent;
import com.android.systemui.recents.events.activity.ShowHistoryButtonEvent;
import com.android.systemui.recents.events.activity.ShowHistoryEvent;
import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
import com.android.systemui.recents.events.ui.UserInteractionEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
import com.android.systemui.recents.events.ui.dragndrop.DragStartInitializeDropTargetsEvent;
import com.android.systemui.recents.events.ui.focus.DismissFocusedTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusNextTaskViewEvent;
import com.android.systemui.recents.events.ui.focus.FocusPreviousTaskViewEvent;
import com.android.systemui.recents.misc.DozeTrigger;
import com.android.systemui.recents.misc.ReferenceCountedTrigger;
import com.android.systemui.recents.misc.SystemServicesProxy;
import com.android.systemui.recents.misc.Utilities;
import com.android.systemui.recents.model.Task;
import com.android.systemui.recents.model.TaskStack;

import java.util.ArrayList;
import java.util.List;


/* The visual representation of a task stack view */
public class TaskStackView extends FrameLayout implements TaskStack.TaskStackCallbacks,
        TaskView.TaskViewCallbacks, TaskStackViewScroller.TaskStackViewScrollerCallbacks,
        TaskStackLayoutAlgorithm.TaskStackLayoutAlgorithmCallbacks,
        ViewPool.ViewPoolConsumer<TaskView, Task> {

    private final static String KEY_SAVED_STATE_SUPER = "saved_instance_state_super";
    private final static String KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE =
            "saved_instance_state_layout_focused_state";
    private final static String KEY_SAVED_STATE_LAYOUT_STACK_SCROLL =
            "saved_instance_state_layout_stack_scroll";

    // The thresholds at which to show/hide the history button.
    private static final float SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD = 0.3f;
    private static final float HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD = 0.3f;

    public static final int DEFAULT_SYNC_STACK_DURATION = 200;
    private static final int DRAG_SCALE_DURATION = 175;
    private static final float DRAG_SCALE_FACTOR = 1.05f;

    private static final ArraySet<Task.TaskKey> EMPTY_TASK_SET = new ArraySet<>();

    LayoutInflater mInflater;
    TaskStack mStack = new TaskStack();
    @ViewDebug.ExportedProperty(deepExport=true, prefix="layout_")
    TaskStackLayoutAlgorithm mLayoutAlgorithm;
    @ViewDebug.ExportedProperty(deepExport=true, prefix="scroller_")
    TaskStackViewScroller mStackScroller;
    @ViewDebug.ExportedProperty(deepExport=true, prefix="touch_")
    TaskStackViewTouchHandler mTouchHandler;
    TaskStackAnimationHelper mAnimationHelper;
    GradientDrawable mFreeformWorkspaceBackground;
    ObjectAnimator mFreeformWorkspaceBackgroundAnimator;
    ViewPool<TaskView, Task> mViewPool;

    ArrayList<TaskView> mTaskViews = new ArrayList<>();
    ArrayList<TaskViewTransform> mCurrentTaskTransforms = new ArrayList<>();
    ArraySet<Task.TaskKey> mIgnoreTasks = new ArraySet<>();
    AnimationProps mDeferredTaskViewLayoutAnimation = null;

    @ViewDebug.ExportedProperty(deepExport=true, prefix="doze_")
    DozeTrigger mUIDozeTrigger;
    @ViewDebug.ExportedProperty(deepExport=true, prefix="focused_task_")
    Task mFocusedTask;

    int mTaskCornerRadiusPx;
    private int mDividerSize;
    private int mStartTimerIndicatorDuration;

    @ViewDebug.ExportedProperty(category="recents")
    boolean mTaskViewsClipDirty = true;
    @ViewDebug.ExportedProperty(category="recents")
    boolean mAwaitingFirstLayout = true;
    @ViewDebug.ExportedProperty(category="recents")
    boolean mInMeasureLayout = false;
    @ViewDebug.ExportedProperty(category="recents")
    boolean mEnterAnimationComplete = false;
    @ViewDebug.ExportedProperty(category="recents")
    boolean mTouchExplorationEnabled;
    @ViewDebug.ExportedProperty(category="recents")
    boolean mScreenPinningEnabled;

    // The stable stack bounds are the full bounds that we were measured with from RecentsView
    @ViewDebug.ExportedProperty(category="recents")
    private Rect mStableStackBounds = new Rect();
    // The current stack bounds are dynamic and may change as the user drags and drops
    @ViewDebug.ExportedProperty(category="recents")
    private Rect mStackBounds = new Rect();

    private Rect mTmpRect = new Rect();
    private ArrayMap<Task.TaskKey, TaskView> mTmpTaskViewMap = new ArrayMap<>();
    private List<TaskView> mTmpTaskViews = new ArrayList<>();
    private TaskViewTransform mTmpTransform = new TaskViewTransform();
    private int[] mTmpIntPair = new int[2];

    // A convenience update listener to request updating clipping of tasks
    private ValueAnimator.AnimatorUpdateListener mRequestUpdateClippingListener =
            new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    if (!mTaskViewsClipDirty) {
                        mTaskViewsClipDirty = true;
                        invalidate();
                    }
                }
            };

    // The drop targets for a task drag
    private DropTarget mFreeformWorkspaceDropTarget = new DropTarget() {
        @Override
        public boolean acceptsDrop(int x, int y, int width, int height, boolean isCurrentTarget) {
            // This drop target has a fixed bounds and should be checked last, so just fall through
            // if it is the current target
            if (!isCurrentTarget) {
                return mLayoutAlgorithm.mFreeformRect.contains(x, y);
            }
            return false;
        }
    };

    private DropTarget mStackDropTarget = new DropTarget() {
        @Override
        public boolean acceptsDrop(int x, int y, int width, int height, boolean isCurrentTarget) {
            // This drop target has a fixed bounds and should be checked last, so just fall through
            // if it is the current target
            if (!isCurrentTarget) {
                return mLayoutAlgorithm.mStackRect.contains(x, y);
            }
            return false;
        }
    };

    public TaskStackView(Context context) {
        super(context);
        SystemServicesProxy ssp = Recents.getSystemServices();
        Resources res = context.getResources();

        // Set the stack first
        mStack.setCallbacks(this);
        mViewPool = new ViewPool<>(context, this);
        mInflater = LayoutInflater.from(context);
        mLayoutAlgorithm = new TaskStackLayoutAlgorithm(context, this);
        mStackScroller = new TaskStackViewScroller(context, this, mLayoutAlgorithm);
        mTouchHandler = new TaskStackViewTouchHandler(context, this, mStackScroller);
        mAnimationHelper = new TaskStackAnimationHelper(context, this);
        mTaskCornerRadiusPx = res.getDimensionPixelSize(
                R.dimen.recents_task_view_rounded_corners_radius);
        mDividerSize = ssp.getDockedDividerSize(context);

        int taskBarDismissDozeDelaySeconds = getResources().getInteger(
                R.integer.recents_task_bar_dismiss_delay_seconds);
        mUIDozeTrigger = new DozeTrigger(taskBarDismissDozeDelaySeconds, new Runnable() {
            @Override
            public void run() {
                // Show the task bar dismiss buttons
                List<TaskView> taskViews = getTaskViews();
                int taskViewCount = taskViews.size();
                for (int i = 0; i < taskViewCount; i++) {
                    TaskView tv = taskViews.get(i);
                    tv.startNoUserInteractionAnimation();
                }
            }
        });
        setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);

        mFreeformWorkspaceBackground = (GradientDrawable) getContext().getDrawable(
                R.drawable.recents_freeform_workspace_bg);
        mFreeformWorkspaceBackground.setCallback(this);
        if (ssp.hasFreeformWorkspaceSupport()) {
            mFreeformWorkspaceBackground.setColor(
                    getContext().getColor(R.color.recents_freeform_workspace_bg_color));
        }
    }

    /**
     * Called only if we are resuming Recents.
     */
    void onResume(boolean isResumingFromVisible) {
        if (!isResumingFromVisible) {
            // Reset the focused task
            resetFocusedTask(getFocusedTask());
        }

        // Reset the state of each of the task views
        List<TaskView> taskViews = new ArrayList<>();
        taskViews.addAll(getTaskViews());
        taskViews.addAll(mViewPool.getViews());
        for (int i = taskViews.size() - 1; i >= 0; i--) {
            taskViews.get(i).onResume(isResumingFromVisible);
        }

        // Reset the stack state
        readSystemFlags();
        mTaskViewsClipDirty = true;
        mEnterAnimationComplete = false;
        mUIDozeTrigger.stopDozing();
        if (isResumingFromVisible) {
            // Animate in the freeform workspace
            int ffBgAlpha = mLayoutAlgorithm.getStackState().freeformBackgroundAlpha;
            animateFreeformWorkspaceBackgroundAlpha(ffBgAlpha, new AnimationProps(150,
                    Interpolators.FAST_OUT_SLOW_IN));
        } else {
            mStackScroller.reset();
            mLayoutAlgorithm.reset();
            mAwaitingFirstLayout = true;
            requestLayout();
        }
    }

    @Override
    protected void onAttachedToWindow() {
        EventBus.getDefault().register(this, RecentsActivity.EVENT_BUS_PRIORITY + 1);
        super.onAttachedToWindow();
        readSystemFlags();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        EventBus.getDefault().unregister(this);
    }

    /**
     * Sets the stack tasks of this TaskStackView from the given TaskStack.
     */
    public void setTasks(TaskStack stack, boolean notifyStackChanges, boolean relayoutTaskStack) {
        boolean isInitialized = mLayoutAlgorithm.isInitialized();
        mStack.setTasks(getContext(), stack.computeAllTasksList(),
                notifyStackChanges && isInitialized);
        if (isInitialized) {
            // Only update the layout if we are notifying, otherwise, we will update it in the next
            // measure/layout pass
            updateLayoutAlgorithm(false /* boundScroll */, EMPTY_TASK_SET);
            updateToInitialState();

            if (relayoutTaskStack) {
                relayoutTaskViews(AnimationProps.IMMEDIATE);

                // Rebind all the task views.  This will not trigger new resources to be loaded
                // unless they have actually changed
                List<TaskView> taskViews = getTaskViews();
                int taskViewCount = taskViews.size();
                for (int i = 0; i < taskViewCount; i++) {
                    TaskView tv = taskViews.get(i);
                    bindTaskView(tv, tv.getTask());
                }
            }
        }
    }

    /** Returns the task stack. */
    public TaskStack getStack() {
        return mStack;
    }

    /**
     * Updates this TaskStackView to the initial state.
     */
    public void updateToInitialState() {
        mStackScroller.setStackScrollToInitialState();
        mLayoutAlgorithm.updateToInitialState(mStack.getStackTasks());
    }

    /** Updates the list of task views */
    void updateTaskViewsList() {
        mTaskViews.clear();
        int childCount = getChildCount();
        for (int i = 0; i < childCount; i++) {
            View v = getChildAt(i);
            if (v instanceof TaskView) {
                mTaskViews.add((TaskView) v);
            }
        }
    }

    /** Gets the list of task views */
    List<TaskView> getTaskViews() {
        return mTaskViews;
    }

    /**
     * Returns the front most task view.
     *
     * @param stackTasksOnly if set, will return the front most task view in the stack (by default
     *                       the front most task view will be freeform since they are placed above
     *                       stack tasks)
     */
    private TaskView getFrontMostTaskView(boolean stackTasksOnly) {
        List<TaskView> taskViews = getTaskViews();
        int taskViewCount = taskViews.size();
        for (int i = taskViewCount - 1; i >= 0; i--) {
            TaskView tv = taskViews.get(i);
            Task task = tv.getTask();
            if (stackTasksOnly && task.isFreeformTask()) {
                continue;
            }
            return tv;
        }
        return null;
    }

    /**
     * Finds the child view given a specific {@param task}.
     */
    public TaskView getChildViewForTask(Task t) {
        List<TaskView> taskViews = getTaskViews();
        int taskViewCount = taskViews.size();
        for (int i = 0; i < taskViewCount; i++) {
            TaskView tv = taskViews.get(i);
            if (tv.getTask() == t) {
                return tv;
            }
        }
        return null;
    }

    /** Returns the stack algorithm for this task stack. */
    public TaskStackLayoutAlgorithm getStackAlgorithm() {
        return mLayoutAlgorithm;
    }

    /**
     * Adds a task to the ignored set.
     */
    void addIgnoreTask(Task task) {
        mIgnoreTasks.add(task.key);
    }

    /**
     * Removes a task from the ignored set.
     */
    void removeIgnoreTask(Task task) {
        mIgnoreTasks.remove(task.key);
    }

    /**
     * Returns whether the specified {@param task} is ignored.
     */
    boolean isIgnoredTask(Task task) {
        return mIgnoreTasks.contains(task.key);
    }

    /**
     * Computes the task transforms at the current stack scroll for all visible tasks. If a valid
     * target stack scroll is provided (ie. is different than {@param curStackScroll}), then the
     * visible range includes all tasks at the target stack scroll. This is useful for ensure that
     * all views necessary for a transition or animation will be visible at the start.
     *
     * This call ignores freeform tasks.
     *
     * @param taskTransforms The set of task view transforms to reuse, this list will be sized to
     *                       match the size of {@param tasks}
     * @param tasks The set of tasks for which to generate transforms
     * @param curStackScroll The current stack scroll
     * @param targetStackScroll The stack scroll that we anticipate we are going to be scrolling to.
     *                          The range of the union of the visible views at the current and
     *                          target stack scrolls will be returned.
     * @param ignoreTasksSet The set of tasks to skip for purposes of calculaing the visible range.
     *                       Transforms will still be calculated for the ignore tasks.
     * @return the front and back most visible task indices (there may be non visible tasks in
     *         between this range)
     */
    int[] computeVisibleTaskTransforms(ArrayList<TaskViewTransform> taskTransforms,
            ArrayList<Task> tasks, float curStackScroll, float targetStackScroll,
            ArraySet<Task.TaskKey> ignoreTasksSet, boolean ignoreTaskOverrides) {
        int taskCount = tasks.size();
        int[] visibleTaskRange = mTmpIntPair;
        visibleTaskRange[0] = -1;
        visibleTaskRange[1] = -1;
        boolean useTargetStackScroll = Float.compare(curStackScroll, targetStackScroll) != 0;

        // We can reuse the task transforms where possible to reduce object allocation
        Utilities.matchTaskListSize(tasks, taskTransforms);

        // Update the stack transforms
        TaskViewTransform frontTransform = null;
        TaskViewTransform frontTransformAtTarget = null;
        TaskViewTransform transform = null;
        TaskViewTransform transformAtTarget = null;
        for (int i = taskCount - 1; i >= 0; i--) {
            Task task = tasks.get(i);

            // Calculate the current and (if necessary) the target transform for the task
            transform = mLayoutAlgorithm.getStackTransform(task, curStackScroll,
                    taskTransforms.get(i), frontTransform, ignoreTaskOverrides);
            if (useTargetStackScroll && !transform.visible) {
                // If we have a target stack scroll and the task is not currently visible, then we
                // just update the transform at the new scroll
                // TODO: Optimize this
                transformAtTarget = mLayoutAlgorithm.getStackTransform(task,
                        targetStackScroll, new TaskViewTransform(), frontTransformAtTarget);
                if (transformAtTarget.visible) {
                    transform.copyFrom(transformAtTarget);
                }
            }

            // For ignore tasks, only calculate the stack transform and skip the calculation of the
            // visible stack indices
            if (ignoreTasksSet.contains(task.key)) {
                continue;
            }

            // For freeform tasks, only calculate the stack transform and skip the calculation of
            // the visible stack indices
            if (task.isFreeformTask()) {
                continue;
            }

            frontTransform = transform;
            frontTransformAtTarget = transformAtTarget;
            if (transform.visible) {
                if (visibleTaskRange[0] < 0) {
                    visibleTaskRange[0] = i;
                }
                visibleTaskRange[1] = i;
            }
        }
        return visibleTaskRange;
    }

    /**
     * Binds the visible {@link TaskView}s at the given target scroll.
     */
    void bindVisibleTaskViews(float targetStackScroll) {
        bindVisibleTaskViews(targetStackScroll, mIgnoreTasks, false /* ignoreTaskOverrides */);
    }

    void bindVisibleTaskViews(float targetStackScroll, boolean ignoreTaskOverrides) {
        bindVisibleTaskViews(targetStackScroll, mIgnoreTasks, ignoreTaskOverrides);
    }

    /**
     * Synchronizes the set of children {@link TaskView}s to match the visible set of tasks in the
     * current {@link TaskStack}. This call does not continue on to update their position to the
     * computed {@link TaskViewTransform}s of the visible range, but only ensures that they will
     * be added/removed from the view hierarchy and placed in the correct Z order and initial
     * position (if not currently on screen).
     *
     * @param targetStackScroll If provided, will ensure that the set of visible {@link TaskView}s
     *                          includes those visible at the current stack scroll, and all at the
     *                          target stack scroll.
     * @param ignoreTasksSet The set of tasks to ignore in this rebinding of the visible
     *                       {@link TaskView}s
     * @param ignoreTaskOverrides If set, the visible task computation will get the transforms for
     *                            tasks at their non-overridden task progress
     */
    void bindVisibleTaskViews(float targetStackScroll, ArraySet<Task.TaskKey> ignoreTasksSet,
            boolean ignoreTaskOverrides) {
        // Get all the task transforms
        ArrayList<Task> tasks = mStack.getStackTasks();
        int[] visibleTaskRange = computeVisibleTaskTransforms(mCurrentTaskTransforms, tasks,
                mStackScroller.getStackScroll(), targetStackScroll, ignoreTasksSet,
                ignoreTaskOverrides);

        // Return all the invisible children to the pool
        mTmpTaskViewMap.clear();
        List<TaskView> taskViews = getTaskViews();
        int lastFocusedTaskIndex = -1;
        int taskViewCount = taskViews.size();
        for (int i = taskViewCount - 1; i >= 0; i--) {
            TaskView tv = taskViews.get(i);
            Task task = tv.getTask();

            // Skip ignored tasks
            if (ignoreTasksSet.contains(task.key)) {
                continue;
            }

            // It is possible for the set of lingering TaskViews to differ from the stack if the
            // stack was updated before the relayout.  If the task view is no longer in the stack,
            // then just return it back to the view pool.
            int taskIndex = mStack.indexOfStackTask(task);
            TaskViewTransform transform = null;
            if (taskIndex != -1) {
                transform = mCurrentTaskTransforms.get(taskIndex);
            }

            if (task.isFreeformTask() || (transform != null && transform.visible)) {
                mTmpTaskViewMap.put(task.key, tv);
            } else {
                if (mTouchExplorationEnabled) {
                    lastFocusedTaskIndex = taskIndex;
                    resetFocusedTask(task);
                }
                mViewPool.returnViewToPool(tv);
            }
        }

        // Pick up all the newly visible children
        for (int i = tasks.size() - 1; i >= 0; i--) {
            Task task = tasks.get(i);
            TaskViewTransform transform = mCurrentTaskTransforms.get(i);

            // Skip ignored tasks
            if (ignoreTasksSet.contains(task.key)) {
                continue;
            }

            // Skip the invisible non-freeform stack tasks
            if (!task.isFreeformTask() && !transform.visible) {
                continue;
            }

            TaskView tv = mTmpTaskViewMap.get(task.key);
            if (tv == null) {
                tv = mViewPool.pickUpViewFromPool(task, task);
                if (task.isFreeformTask()) {
                    tv.updateViewPropertiesToTaskTransform(transform, AnimationProps.IMMEDIATE,
                            mRequestUpdateClippingListener);
                } else {
                    if (transform.rect.top <= mLayoutAlgorithm.mStackRect.top) {
                        tv.updateViewPropertiesToTaskTransform(
                                mLayoutAlgorithm.getBackOfStackTransform(),
                                AnimationProps.IMMEDIATE, mRequestUpdateClippingListener);
                    } else {
                        tv.updateViewPropertiesToTaskTransform(
                                mLayoutAlgorithm.getFrontOfStackTransform(),
                                AnimationProps.IMMEDIATE, mRequestUpdateClippingListener);
                    }
                }
            } else {
                // Reattach it in the right z order
                final int taskIndex = mStack.indexOfStackTask(task);
                final int insertIndex = findTaskViewInsertIndex(task, taskIndex);
                if (insertIndex != getTaskViews().indexOf(tv)){
                    detachViewFromParent(tv);
                    attachViewToParent(tv, insertIndex, tv.getLayoutParams());
                    updateTaskViewsList();
                }
            }
        }

        // Update the focus if the previous focused task was returned to the view pool
        if (lastFocusedTaskIndex != -1) {
            if (lastFocusedTaskIndex < visibleTaskRange[1]) {
                setFocusedTask(visibleTaskRange[1], false /* scrollToTask */,
                        true /* requestViewFocus */);
            } else {
                setFocusedTask(visibleTaskRange[0], false /* scrollToTask */,
                        true /* requestViewFocus */);
            }
        }
    }

    /**
     * Relayout the the visible {@link TaskView}s to their current transforms as specified by the
     * {@link TaskStackLayoutAlgorithm} with the given {@param animation}. This call cancels any
     * animations that are current running on those task views, and will ensure that the children
     * {@link TaskView}s will match the set of visible tasks in the stack.
     *
     * @see #relayoutTaskViews(AnimationProps, ArraySet<Task.TaskKey>)
     */
    void relayoutTaskViews(AnimationProps animation) {
        relayoutTaskViews(animation, mIgnoreTasks);
    }

    /**
     * Relayout the the visible {@link TaskView}s to their current transforms as specified by the
     * {@link TaskStackLayoutAlgorithm} with the given {@param animation}. This call cancels any
     * animations that are current running on those task views, and will ensure that the children
     * {@link TaskView}s will match the set of visible tasks in the stack.
     *
     * @param ignoreTasksSet the set of tasks to ignore in the relayout
     */
    void relayoutTaskViews(AnimationProps animation, ArraySet<Task.TaskKey> ignoreTasksSet) {
        // If we had a deferred animation, cancel that
        mDeferredTaskViewLayoutAnimation = null;

        // Cancel all task view animations
        cancelAllTaskViewAnimations();

        // Synchronize the current set of TaskViews
        bindVisibleTaskViews(mStackScroller.getStackScroll(), ignoreTasksSet,
                false /* ignoreTaskOverrides */);

        // Animate them to their final transforms with the given animation
        List<TaskView> taskViews = getTaskViews();
        int taskViewCount = taskViews.size();
        for (int i = 0; i < taskViewCount; i++) {
            TaskView tv = taskViews.get(i);
            int taskIndex = mStack.indexOfStackTask(tv.getTask());
            TaskViewTransform transform = mCurrentTaskTransforms.get(taskIndex);

            if (ignoreTasksSet.contains(tv.getTask().key)) {
                continue;
            }

            updateTaskViewToTransform(tv, transform, animation);
        }
    }

    /**
     * Posts an update to synchronize the {@link TaskView}s with the stack on the next frame.
     */
    void relayoutTaskViewsOnNextFrame(AnimationProps animation) {
        mDeferredTaskViewLayoutAnimation = animation;
        invalidate();
    }

    /**
     * Called to update a specific {@link TaskView} to a given {@link TaskViewTransform} with a
     * given set of {@link AnimationProps} properties.
     */
    public void updateTaskViewToTransform(TaskView taskView, TaskViewTransform transform,
            AnimationProps animation) {
        taskView.updateViewPropertiesToTaskTransform(transform, animation,
                mRequestUpdateClippingListener);
    }

    /**
     * Returns the current task transforms of all tasks, falling back to the stack layout if there
     * is no {@link TaskView} for the task.
     */
    public void getCurrentTaskTransforms(ArrayList<Task> tasks,
            ArrayList<TaskViewTransform> transformsOut) {
        Utilities.matchTaskListSize(tasks, transformsOut);
        int focusState = mLayoutAlgorithm.getFocusState();
        for (int i = tasks.size() - 1; i >= 0; i--) {
            Task task = tasks.get(i);
            TaskViewTransform transform = transformsOut.get(i);
            TaskView tv = getChildViewForTask(task);
            if (tv != null) {
                transform.fillIn(tv);
            } else {
                mLayoutAlgorithm.getStackTransform(task, mStackScroller.getStackScroll(),
                        focusState, transform, null, true /* forceUpdate */,
                        false /* ignoreTaskOverrides */);
            }
            transform.visible = true;
        }
    }

    /**
     * Returns the task transforms for all the tasks in the stack if the stack was at the given
     * {@param stackScroll} and {@param focusState}.
     */
    public void getLayoutTaskTransforms(float stackScroll, int focusState, ArrayList<Task> tasks,
            ArrayList<TaskViewTransform> transformsOut) {
        Utilities.matchTaskListSize(tasks, transformsOut);
        for (int i = tasks.size() - 1; i >= 0; i--) {
            Task task = tasks.get(i);
            TaskViewTransform transform = transformsOut.get(i);
            mLayoutAlgorithm.getStackTransform(task, stackScroll, focusState, transform, null,
                    true /* forceUpdate */, true /* ignoreTaskOverrides */);
            transform.visible = true;
        }
    }

    /**
     * Cancels the next deferred task view layout.
     */
    void cancelDeferredTaskViewLayoutAnimation() {
        mDeferredTaskViewLayoutAnimation = null;
    }

    /**
     * Cancels all {@link TaskView} animations.
     *
     * @see #cancelAllTaskViewAnimations(ArraySet<Task.TaskKey>)
     */
    void cancelAllTaskViewAnimations() {
        cancelAllTaskViewAnimations(mIgnoreTasks);
    }

    /**
     * Cancels all {@link TaskView} animations.
     *
     * @param ignoreTasksSet The set of tasks to continue running their animations.
     */
    void cancelAllTaskViewAnimations(ArraySet<Task.TaskKey> ignoreTasksSet) {
        List<TaskView> taskViews = getTaskViews();
        for (int i = taskViews.size() - 1; i >= 0; i--) {
            final TaskView tv = taskViews.get(i);
            if (!ignoreTasksSet.contains(tv.getTask().key)) {
                tv.cancelTransformAnimation();
            }
        }
    }

    /**
     * Updates the clip for each of the task views from back to front.
     */
    private void clipTaskViews() {
        RecentsConfiguration config = Recents.getConfiguration();

        // Update the clip on each task child
        List<TaskView> taskViews = getTaskViews();
        TaskView tmpTv = null;
        TaskView prevVisibleTv = null;
        int taskViewCount = taskViews.size();
        for (int i = 0; i < taskViewCount; i++) {
            TaskView tv = taskViews.get(i);
            TaskView frontTv = null;
            int clipBottom = 0;

            if (isIgnoredTask(tv.getTask())) {
                // For each of the ignore tasks, update the translationZ of its TaskView to be
                // between the translationZ of the tasks immediately underneath it
                if (prevVisibleTv != null) {
                    tv.setTranslationZ(Math.max(tv.getTranslationZ(),
                            prevVisibleTv.getTranslationZ() + 0.1f));
                }
            }

            if (i < (taskViewCount - 1) && tv.shouldClipViewInStack()) {
                // Find the next view to clip against
                for (int j = i + 1; j < taskViewCount; j++) {
                    tmpTv = taskViews.get(j);

                    if (tmpTv.shouldClipViewInStack()) {
                        frontTv = tmpTv;
                        break;
                    }
                }

                // Clip against the next view, this is just an approximation since we are
                // stacked and we can make assumptions about the visibility of the this
                // task relative to the ones in front of it.
                if (frontTv != null) {
                    float taskBottom = tv.getBottom();
                    float frontTaskTop = frontTv.getTop();
                    if (frontTaskTop < taskBottom) {
                        // Map the stack view space coordinate (the rects) to view space
                        clipBottom = (int) (taskBottom - frontTaskTop) - mTaskCornerRadiusPx;
                    }
                }
            }
            tv.getViewBounds().setClipBottom(clipBottom);
            tv.mThumbnailView.updateThumbnailVisibility(clipBottom - tv.getPaddingBottom());
            prevVisibleTv = tv;
        }
        mTaskViewsClipDirty = false;
    }

    /**
     * Updates the layout algorithm min and max virtual scroll bounds.
     *
     * @see #updateLayoutAlgorithm(boolean, ArraySet<Task.TaskKey>)
     */
    void updateLayoutAlgorithm(boolean boundScrollToNewMinMax) {
        updateLayoutAlgorithm(boundScrollToNewMinMax, mIgnoreTasks);
    }

    /**
     * Updates the min and max virtual scroll bounds.
     *
     * @param ignoreTasksSet the set of tasks to ignore in the relayout
     */
    void updateLayoutAlgorithm(boolean boundScrollToNewMinMax,
            ArraySet<Task.TaskKey> ignoreTasksSet) {
        // Compute the min and max scroll values
        mLayoutAlgorithm.update(mStack, ignoreTasksSet);

        // Update the freeform workspace background
        SystemServicesProxy ssp = Recents.getSystemServices();
        if (ssp.hasFreeformWorkspaceSupport()) {
            mTmpRect.set(mLayoutAlgorithm.mFreeformRect);
            mFreeformWorkspaceBackground.setBounds(mTmpRect);
        }

        if (boundScrollToNewMinMax) {
            mStackScroller.boundScroll();
        }
    }

    /** Returns the scroller. */
    public TaskStackViewScroller getScroller() {
        return mStackScroller;
    }

    /**
     * Sets the focused task to the provided (bounded taskIndex).
     *
     * @return whether or not the stack will scroll as a part of this focus change
     */
    private boolean setFocusedTask(int taskIndex, boolean scrollToTask,
            final boolean requestViewFocus) {
        return setFocusedTask(taskIndex, scrollToTask, requestViewFocus, 0);
    }

    /**
     * Sets the focused task to the provided (bounded focusTaskIndex).
     *
     * @return whether or not the stack will scroll as a part of this focus change
     */
    private boolean setFocusedTask(int focusTaskIndex, boolean scrollToTask,
            boolean requestViewFocus, int timerIndicatorDuration) {
        // Find the next task to focus
        int newFocusedTaskIndex = mStack.getTaskCount() > 0 ?
                Utilities.clamp(focusTaskIndex, 0, mStack.getTaskCount() - 1) : -1;
        final Task newFocusedTask = (newFocusedTaskIndex != -1) ?
                mStack.getStackTasks().get(newFocusedTaskIndex) : null;

        // Reset the last focused task state if changed
        if (mFocusedTask != null) {
            // Cancel the timer indicator, if applicable
            if (timerIndicatorDuration > 0) {
                final TaskView tv = getChildViewForTask(mFocusedTask);
                if (tv != null) {
                    tv.getHeaderView().cancelFocusTimerIndicator();
                }
            }

            resetFocusedTask(mFocusedTask);
        }

        boolean willScroll = false;
        mFocusedTask = newFocusedTask;

        if (newFocusedTask != null) {
            // Start the timer indicator, if applicable
            if (timerIndicatorDuration > 0) {
                final TaskView tv = getChildViewForTask(mFocusedTask);
                if (tv != null) {
                    tv.getHeaderView().startFocusTimerIndicator(timerIndicatorDuration);
                } else {
                    // The view is null; set a flag for later
                    mStartTimerIndicatorDuration = timerIndicatorDuration;
                }
            }

            if (scrollToTask) {
                // Cancel any running enter animations at this point when we scroll or change focus
                if (!mEnterAnimationComplete) {
                    cancelAllTaskViewAnimations();
                }

                mLayoutAlgorithm.clearUnfocusedTaskOverrides();
                willScroll = mAnimationHelper.startScrollToFocusedTaskAnimation(newFocusedTask,
                        requestViewFocus);
            } else {
                // Focus the task view
                TaskView newFocusedTaskView = getChildViewForTask(newFocusedTask);
                if (newFocusedTaskView != null) {
                    newFocusedTaskView.setFocusedState(true, requestViewFocus);
                }
            }
        }
        return willScroll;
    }

    /**
     * Sets the focused task relative to the currently focused task.
     *
     * @param forward whether to go to the next task in the stack (along the curve) or the previous
     * @param stackTasksOnly if set, will ensure that the traversal only goes along stack tasks, and
     *                       if the currently focused task is not a stack task, will set the focus
     *                       to the first visible stack task
     * @param animated determines whether to actually draw the highlight along with the change in
     *                            focus.
     */
    public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated) {
        setRelativeFocusedTask(forward, stackTasksOnly, animated, false);
    }

    /**
     * Sets the focused task relative to the currently focused task.
     *
     * @param forward whether to go to the next task in the stack (along the curve) or the previous
     * @param stackTasksOnly if set, will ensure that the traversal only goes along stack tasks, and
     *                       if the currently focused task is not a stack task, will set the focus
     *                       to the first visible stack task
     * @param animated determines whether to actually draw the highlight along with the change in
     *                            focus.
     * @param cancelWindowAnimations if set, will attempt to cancel window animations if a scroll
     *                               happens.
     */
    public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated,
                                       boolean cancelWindowAnimations) {
        setRelativeFocusedTask(forward, stackTasksOnly, animated, cancelWindowAnimations, 0);
    }

    /**
     * Sets the focused task relative to the currently focused task.
     *
     * @param forward whether to go to the next task in the stack (along the curve) or the previous
     * @param stackTasksOnly if set, will ensure that the traversal only goes along stack tasks, and
     *                       if the currently focused task is not a stack task, will set the focus
     *                       to the first visible stack task
     * @param animated determines whether to actually draw the highlight along with the change in
     *                            focus.
     * @param cancelWindowAnimations if set, will attempt to cancel window animations if a scroll
     *                               happens.
     * @param timerIndicatorDuration the duration to initialize the auto-advance timer indicator
     */
    public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated,
                                       boolean cancelWindowAnimations,
                                       int timerIndicatorDuration) {
        int newIndex = mStack.indexOfStackTask(mFocusedTask);
        if (mFocusedTask != null) {
            if (stackTasksOnly) {
                List<Task> tasks =  mStack.getStackTasks();
                if (mFocusedTask.isFreeformTask()) {
                    // Try and focus the front most stack task
                    TaskView tv = getFrontMostTaskView(stackTasksOnly);
                    if (tv != null) {
                        newIndex = mStack.indexOfStackTask(tv.getTask());
                    }
                } else {
                    // Try the next task if it is a stack task
                    int tmpNewIndex = newIndex + (forward ? -1 : 1);
                    if (0 <= tmpNewIndex && tmpNewIndex < tasks.size()) {
                        Task t = tasks.get(tmpNewIndex);
                        if (!t.isFreeformTask()) {
                            newIndex = tmpNewIndex;
                        }
                    }
                }
            } else {
                // No restrictions, lets just move to the new task (looping forward/backwards if
                // necessary)
                int taskCount = mStack.getTaskCount();
                newIndex = (newIndex + (forward ? -1 : 1) + taskCount) % taskCount;
            }
        } else {
            // We don't have a focused task
            float stackScroll = mStackScroller.getStackScroll();
            ArrayList<Task> tasks = mStack.getStackTasks();
            int taskCount = tasks.size();
            if (forward) {
                // Walk backwards and focus the next task smaller than the current stack scroll
                for (newIndex = taskCount - 1; newIndex >= 0; newIndex--) {
                    float taskP = mLayoutAlgorithm.getStackScrollForTask(tasks.get(newIndex));
                    if (Float.compare(taskP, stackScroll) <= 0) {
                        break;
                    }
                }
            } else {
                // Walk forwards and focus the next task larger than the current stack scroll
                for (newIndex = 0; newIndex < taskCount; newIndex++) {
                    float taskP = mLayoutAlgorithm.getStackScrollForTask(tasks.get(newIndex));
                    if (Float.compare(taskP, stackScroll) >= 0) {
                        break;
                    }
                }
            }
        }
        if (newIndex != -1) {
            boolean willScroll = setFocusedTask(newIndex, true /* scrollToTask */,
                    true /* requestViewFocus */, timerIndicatorDuration);
            if (willScroll && cancelWindowAnimations) {
                // As we iterate to the next/previous task, cancel any current/lagging window
                // transition animations
                EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(null));
            }
        }
    }

    /**
     * Resets the focused task.
     */
    void resetFocusedTask(Task task) {
        if (task != null) {
            TaskView tv = getChildViewForTask(task);
            if (tv != null) {
                tv.setFocusedState(false, false /* requestViewFocus */);
            }
        }
        mFocusedTask = null;
    }

    /**
     * Returns the focused task.
     */
    Task getFocusedTask() {
        return mFocusedTask;
    }

    @Override
    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
        super.onInitializeAccessibilityEvent(event);
        List<TaskView> taskViews = getTaskViews();
        int taskViewCount = taskViews.size();
        if (taskViewCount > 0) {
            TaskView backMostTask = taskViews.get(0);
            TaskView frontMostTask = taskViews.get(taskViewCount - 1);
            event.setFromIndex(mStack.indexOfStackTask(backMostTask.getTask()));
            event.setToIndex(mStack.indexOfStackTask(frontMostTask.getTask()));
            event.setContentDescription(frontMostTask.getTask().title);
        }
        event.setItemCount(mStack.getTaskCount());
        event.setScrollY(mStackScroller.mScroller.getCurrY());
        event.setMaxScrollY(mStackScroller.progressToScrollRange(mLayoutAlgorithm.mMaxScrollP));
    }

    @Override
    public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
        super.onInitializeAccessibilityNodeInfo(info);
        List<TaskView> taskViews = getTaskViews();
        int taskViewCount = taskViews.size();
        if (taskViewCount > 1 && mFocusedTask != null) {
            info.setScrollable(true);
            int focusedTaskIndex = mStack.indexOfStackTask(mFocusedTask);
            if (focusedTaskIndex > 0) {
                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
            }
            if (focusedTaskIndex < mStack.getTaskCount() - 1) {
                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
            }
        }
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        Bundle savedState = new Bundle();
        savedState.putParcelable(KEY_SAVED_STATE_SUPER, super.onSaveInstanceState());
        savedState.putInt(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE, mLayoutAlgorithm.getFocusState());
        savedState.putFloat(KEY_SAVED_STATE_LAYOUT_STACK_SCROLL, mStackScroller.getStackScroll());
        return super.onSaveInstanceState();
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        Bundle savedState = (Bundle) state;
        super.onRestoreInstanceState(savedState.getParcelable(KEY_SAVED_STATE_SUPER));

        mLayoutAlgorithm.setFocusState(savedState.getInt(KEY_SAVED_STATE_LAYOUT_FOCUSED_STATE));
        mStackScroller.setStackScroll(savedState.getFloat(KEY_SAVED_STATE_LAYOUT_STACK_SCROLL));
    }

    @Override
    public CharSequence getAccessibilityClassName() {
        return TaskStackView.class.getName();
    }

    @Override
    public boolean performAccessibilityAction(int action, Bundle arguments) {
        if (super.performAccessibilityAction(action, arguments)) {
            return true;
        }
        switch (action) {
            case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
                setRelativeFocusedTask(true, false /* stackTasksOnly */, false /* animated */);
                return true;
            }
            case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
                setRelativeFocusedTask(false, false /* stackTasksOnly */, false /* animated */);
                return true;
            }
        }
        return false;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        return mTouchHandler.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        return mTouchHandler.onTouchEvent(ev);
    }

    @Override
    public boolean onGenericMotionEvent(MotionEvent ev) {
        return mTouchHandler.onGenericMotionEvent(ev);
    }

    @Override
    public void computeScroll() {
        if (mStackScroller.computeScroll()) {
            // Notify accessibility
            sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SCROLLED);
        }
        if (mDeferredTaskViewLayoutAnimation != null) {
            relayoutTaskViews(mDeferredTaskViewLayoutAnimation);
            mTaskViewsClipDirty = true;
            mDeferredTaskViewLayoutAnimation = null;
        }
        if (mTaskViewsClipDirty) {
            clipTaskViews();
        }
    }

    /**
     * Computes the maximum number of visible tasks and thumbnails. Requires that
     * updateLayoutForStack() is called first.
     */
    public TaskStackLayoutAlgorithm.VisibilityReport computeStackVisibilityReport() {
        return mLayoutAlgorithm.computeStackVisibilityReport(mStack.getStackTasks());
    }

    /**
     * Updates the expected task stack bounds for this stack view.
     */
    public void setTaskStackBounds(Rect taskStackBounds, Rect systemInsets) {
        // We can get spurious measure passes with the old bounds when docking, and since we are
        // using the current stack bounds during drag and drop, don't overwrite them until we
        // actually get new bounds
        boolean requiresLayout = false;
        if (!taskStackBounds.equals(mStableStackBounds)) {
            mStableStackBounds.set(taskStackBounds);
            mStackBounds.set(taskStackBounds);
            requiresLayout = true;
        }
        if (!systemInsets.equals(mLayoutAlgorithm.mSystemInsets)) {
            mLayoutAlgorithm.setSystemInsets(systemInsets);
            requiresLayout = true;
        }
        if (requiresLayout) {
            requestLayout();
        }
    }

    /**
     * This is called with the full window width and height to allow stack view children to
     * perform the full screen transition down.
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        mInMeasureLayout = true;
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        // Compute the rects in the stack algorithm
        mLayoutAlgorithm.initialize(mStackBounds,
                TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
        updateLayoutAlgorithm(false /* boundScroll */, EMPTY_TASK_SET);

        // If this is the first layout, then scroll to the front of the stack, then update the
        // TaskViews with the stack so that we can lay them out
        // TODO: The second check is a workaround for wacky layouts that we get while docking via
        //       long pressing the recents button
        if (mAwaitingFirstLayout ||
                (mStackScroller.getStackScroll() == mLayoutAlgorithm.mInitialScrollP)) {
            updateToInitialState();
        }

        // Rebind all the views, including the ignore ones
        bindVisibleTaskViews(mStackScroller.getStackScroll(), EMPTY_TASK_SET,
                false /* ignoreTaskOverrides */);

        // Measure each of the TaskViews
        mTmpTaskViews.clear();
        mTmpTaskViews.addAll(getTaskViews());
        mTmpTaskViews.addAll(mViewPool.getViews());
        int taskViewCount = mTmpTaskViews.size();
        for (int i = 0; i < taskViewCount; i++) {
            measureTaskView(mTmpTaskViews.get(i));
        }

        setMeasuredDimension(width, height);
        mInMeasureLayout = false;
    }

    /**
     * Measures a TaskView.
     */
    private void measureTaskView(TaskView tv) {
        if (tv.getBackground() != null) {
            tv.getBackground().getPadding(mTmpRect);
        } else {
            mTmpRect.setEmpty();
        }
        tv.measure(
                MeasureSpec.makeMeasureSpec(
                        mLayoutAlgorithm.mTaskRect.width() + mTmpRect.left + mTmpRect.right,
                        MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(
                        mLayoutAlgorithm.mTaskRect.height() + mTmpRect.top + mTmpRect.bottom,
                        MeasureSpec.EXACTLY));
    }

    /**
     * This is called with the size of the space not including the top or right insets, or the
     * search bar height in portrait (but including the search bar width in landscape, since we want
     * to draw under it.
     */
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        // Layout each of the TaskViews
        mTmpTaskViews.clear();
        mTmpTaskViews.addAll(getTaskViews());
        mTmpTaskViews.addAll(mViewPool.getViews());
        int taskViewCount = mTmpTaskViews.size();
        for (int i = 0; i < taskViewCount; i++) {
            layoutTaskView(mTmpTaskViews.get(i));
        }

        if (changed) {
            if (mStackScroller.isScrollOutOfBounds()) {
                mStackScroller.boundScroll();
            }
        }
        // Relayout all of the task views including the ignored ones
        relayoutTaskViews(AnimationProps.IMMEDIATE, EMPTY_TASK_SET);
        clipTaskViews();

        if (mAwaitingFirstLayout || !mEnterAnimationComplete) {
            mAwaitingFirstLayout = false;
            onFirstLayout();
        }
    }

    /**
     * Lays out a TaskView.
     */
    private void layoutTaskView(TaskView tv) {
        if (tv.getBackground() != null) {
            tv.getBackground().getPadding(mTmpRect);
        } else {
            mTmpRect.setEmpty();
        }
        Rect taskRect = mLayoutAlgorithm.mTaskRect;
        tv.layout(taskRect.left - mTmpRect.left, taskRect.top - mTmpRect.top,
                taskRect.right + mTmpRect.right, taskRect.bottom + mTmpRect.bottom);
    }

    /** Handler for the first layout. */
    void onFirstLayout() {
        // Setup the view for the enter animation
        mAnimationHelper.prepareForEnterAnimation();

        // Animate in the freeform workspace
        int ffBgAlpha = mLayoutAlgorithm.getStackState().freeformBackgroundAlpha;
        animateFreeformWorkspaceBackgroundAlpha(ffBgAlpha, new AnimationProps(150,
                Interpolators.FAST_OUT_SLOW_IN));

        // Set the task focused state without requesting view focus, and leave the focus animations
        // until after the enter-animation
        RecentsConfiguration config = Recents.getConfiguration();
        RecentsActivityLaunchState launchState = config.getLaunchState();
        int focusedTaskIndex = launchState.getInitialFocusTaskIndex(mStack.getTaskCount());
        if (focusedTaskIndex != -1) {
            setFocusedTask(focusedTaskIndex, false /* scrollToTask */,
                    false /* requestViewFocus */);
        }

        // Update the history button visibility
        if (shouldShowHistoryButton() &&
                mStackScroller.getStackScroll() < SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
            EventBus.getDefault().send(new ShowHistoryButtonEvent(false /* translate */));
        } else {
            EventBus.getDefault().send(new HideHistoryButtonEvent());
        }
    }

    public boolean isTouchPointInView(float x, float y, TaskView tv) {
        mTmpRect.set(tv.getLeft(), tv.getTop(), tv.getRight(), tv.getBottom());
        mTmpRect.offset((int) tv.getTranslationX(), (int) tv.getTranslationY());
        return mTmpRect.contains((int) x, (int) y);
    }

    /**
     * Returns a non-ignored task in the {@param tasks} list that can be used as an achor when
     * calculating the scroll position before and after a layout change.
     */
    public Task findAnchorTask(List<Task> tasks, MutableBoolean isFrontMostTask) {
        for (int i = tasks.size() - 1; i >= 0; i--) {
            Task task = tasks.get(i);

            // Ignore deleting tasks
            if (isIgnoredTask(task)) {
                if (i == tasks.size() - 1) {
                    isFrontMostTask.value = true;
                }
                continue;
            }
            return task;
        }
        return null;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // Draw the freeform workspace background
        SystemServicesProxy ssp = Recents.getSystemServices();
        if (ssp.hasFreeformWorkspaceSupport()) {
            if (mFreeformWorkspaceBackground.getAlpha() > 0) {
                mFreeformWorkspaceBackground.draw(canvas);
            }
        }
    }

    @Override
    protected boolean verifyDrawable(Drawable who) {
        if (who == mFreeformWorkspaceBackground) {
            return true;
        }
        return super.verifyDrawable(who);
    }

    /**
     * Launches the freeform tasks.
     */
    public boolean launchFreeformTasks() {
        ArrayList<Task> tasks = mStack.getFreeformTasks();
        if (!tasks.isEmpty()) {
            Task frontTask = tasks.get(tasks.size() - 1);
            if (frontTask != null && frontTask.isFreeformTask()) {
                EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(frontTask),
                        frontTask, null, INVALID_STACK_ID, false));
                return true;
            }
        }
        return false;
    }

    /**** TaskStackCallbacks Implementation ****/

    @Override
    public void onStackTaskAdded(TaskStack stack, Task newTask) {
        // Update the min/max scroll and animate other task views into their new positions
        updateLayoutAlgorithm(true /* boundScroll */);

        // Animate all the tasks into place
        relayoutTaskViews(new AnimationProps(DEFAULT_SYNC_STACK_DURATION,
                Interpolators.FAST_OUT_SLOW_IN));
    }

    /**
     * We expect that the {@link TaskView} associated with the removed task is already hidden.
     */
    @Override
    public void onStackTaskRemoved(TaskStack stack, Task removedTask, boolean wasFrontMostTask,
            Task newFrontMostTask, AnimationProps animation) {
        if (mFocusedTask == removedTask) {
            resetFocusedTask(removedTask);
        }

        // Remove the view associated with this task, we can't rely on updateTransforms
        // to work here because the task is no longer in the list
        TaskView tv = getChildViewForTask(removedTask);
        if (tv != null) {
            mViewPool.returnViewToPool(tv);
        }

        // Remove the task from the ignored set
        removeIgnoreTask(removedTask);

        // If requested, relayout with the given animation
        if (animation != null) {
            updateLayoutAlgorithm(true /* boundScroll */);
            relayoutTaskViews(animation);
        }

        // Update the new front most task's action button
        if (mScreenPinningEnabled && newFrontMostTask != null) {
            TaskView frontTv = getChildViewForTask(newFrontMostTask);
            if (frontTv != null) {
                frontTv.showActionButton(true /* fadeIn */, DEFAULT_SYNC_STACK_DURATION);
            }
        }

        // If there are no remaining tasks, then just close recents
        if (mStack.getTaskCount() == 0) {
            EventBus.getDefault().send(new AllTaskViewsDismissedEvent());
        }
    }

    @Override
    public void onHistoryTaskRemoved(TaskStack stack, Task removedTask,
            AnimationProps animation) {
        // To be implemented
    }

    /**** ViewPoolConsumer Implementation ****/

    @Override
    public TaskView createView(Context context) {
        return (TaskView) mInflater.inflate(R.layout.recents_task_view, this, false);
    }

    @Override
    public void onReturnViewToPool(TaskView tv) {
        final Task task = tv.getTask();

        // Unbind the task from the task view
        unbindTaskView(tv, task);

        // Reset the view properties and view state
        tv.resetViewProperties();
        tv.setFocusedState(false, false /* requestViewFocus */);
        tv.setClipViewInStack(false);
        if (mScreenPinningEnabled) {
            tv.hideActionButton(false /* fadeOut */, 0 /* duration */, false /* scaleDown */, null);
        }

        // Detach the view from the hierarchy
        detachViewFromParent(tv);
        // Update the task views list after removing the task view
        updateTaskViewsList();
    }

    @Override
    public void onPickUpViewFromPool(TaskView tv, Task task, boolean isNewView) {
        // Find the index where this task should be placed in the stack
        int taskIndex = mStack.indexOfStackTask(task);
        int insertIndex = findTaskViewInsertIndex(task, taskIndex);

        // Add/attach the view to the hierarchy
        if (isNewView) {
            if (mInMeasureLayout) {
                // If we are measuring the layout, then just add the view normally as it will be
                // laid out during the layout pass
                addView(tv, insertIndex);
            } else {
                // Otherwise, this is from a bindVisibleTaskViews() call outside the measure/layout
                // pass, and we should layout the new child ourselves
                ViewGroup.LayoutParams params = tv.getLayoutParams();
                if (params == null) {
                    params = generateDefaultLayoutParams();
                }
                addViewInLayout(tv, insertIndex, params, true /* preventRequestLayout */);
                measureTaskView(tv);
                layoutTaskView(tv);
            }
        } else {
            attachViewToParent(tv, insertIndex, tv.getLayoutParams());
        }
        // Update the task views list after adding the new task view
        updateTaskViewsList();

        // Bind the task view to the new task
        bindTaskView(tv, task);

        // If the doze trigger has already fired, then update the state for this task view
        if (mUIDozeTrigger.isAsleep()) {
            tv.setNoUserInteractionState();
        }

        // Set the new state for this view, including the callbacks and view clipping
        tv.setCallbacks(this);
        tv.setTouchEnabled(true);
        tv.setClipViewInStack(true);
        if (mFocusedTask == task) {
            tv.setFocusedState(true, false /* requestViewFocus */);
            if (mStartTimerIndicatorDuration > 0) {
                // The timer indicator couldn't be started before, so start it now
                tv.getHeaderView().startFocusTimerIndicator(mStartTimerIndicatorDuration);
                mStartTimerIndicatorDuration = 0;
            }
        }

        // Restore the action button visibility if it is the front most task view
        if (mScreenPinningEnabled && tv.getTask() ==
                mStack.getStackFrontMostTask(false /* includeFreeform */)) {
            tv.showActionButton(false /* fadeIn */, 0 /* fadeInDuration */);
        }
    }

    @Override
    public boolean hasPreferredData(TaskView tv, Task preferredData) {
        return (tv.getTask() == preferredData);
    }

    private void bindTaskView(TaskView tv, Task task) {
        // Rebind the task and request that this task's data be filled into the TaskView
        tv.onTaskBound(task);

        // Load the task data
        Recents.getTaskLoader().loadTaskData(task, true /* fetchAndInvalidateThumbnails */);
    }

    private void unbindTaskView(TaskView tv, Task task) {
        // Report that this task's data is no longer being used
        Recents.getTaskLoader().unloadTaskData(task);
    }

    /**** TaskViewCallbacks Implementation ****/

    @Override
    public void onTaskViewClipStateChanged(TaskView tv) {
        if (!mTaskViewsClipDirty) {
            mTaskViewsClipDirty = true;
            invalidate();
        }
    }

    /**** TaskStackLayoutAlgorithm.TaskStackLayoutAlgorithmCallbacks ****/

    @Override
    public void onFocusStateChanged(int prevFocusState, int curFocusState) {
        if (mDeferredTaskViewLayoutAnimation == null) {
            mUIDozeTrigger.poke();
            relayoutTaskViewsOnNextFrame(AnimationProps.IMMEDIATE);
        }
    }

    /**** TaskStackViewScroller.TaskStackViewScrollerCallbacks ****/

    @Override
    public void onStackScrollChanged(float prevScroll, float curScroll, AnimationProps animation) {
        mUIDozeTrigger.poke();
        if (animation != null) {
            relayoutTaskViewsOnNextFrame(animation);
        }
        mLayoutAlgorithm.updateFocusStateOnScroll(curScroll, curScroll - prevScroll);

        if (mEnterAnimationComplete) {
            if (shouldShowHistoryButton() &&
                    prevScroll > SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD &&
                    curScroll <= SHOW_HISTORY_BUTTON_SCROLL_THRESHOLD) {
                EventBus.getDefault().send(new ShowHistoryButtonEvent(true /* translate */));
            } else if (prevScroll < HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD &&
                    curScroll >= HIDE_HISTORY_BUTTON_SCROLL_THRESHOLD) {
                EventBus.getDefault().send(new HideHistoryButtonEvent());
            }
        }
    }

    /**** EventBus Events ****/

    public final void onBusEvent(PackagesChangedEvent event) {
        // Compute which components need to be removed
        ArraySet<ComponentName> removedComponents = mStack.computeComponentsRemoved(
                event.packageName, event.userId);

        // For other tasks, just remove them directly if they no longer exist
        ArrayList<Task> tasks = mStack.getStackTasks();
        for (int i = tasks.size() - 1; i >= 0; i--) {
            final Task t = tasks.get(i);
            if (removedComponents.contains(t.key.getComponent())) {
                final TaskView tv = getChildViewForTask(t);
                if (tv != null) {
                    // For visible children, defer removing the task until after the animation
                    tv.dismissTask();
                } else {
                    // Otherwise, remove the task from the stack immediately
                    mStack.removeTask(t, AnimationProps.IMMEDIATE);
                }
            }
        }
    }

    public final void onBusEvent(LaunchTaskEvent event) {
        // Cancel any doze triggers once a task is launched
        mUIDozeTrigger.stopDozing();
    }

    public final void onBusEvent(LaunchNextTaskRequestEvent event) {
        int launchTaskIndex = mStack.indexOfStackTask(mStack.getLaunchTarget());
        if (launchTaskIndex != -1) {
            launchTaskIndex = Math.max(0, launchTaskIndex - 1);
        } else {
            launchTaskIndex = mStack.getTaskCount() - 1;
        }
        if (launchTaskIndex != -1) {
            // Stop all animations
            mUIDozeTrigger.stopDozing();
            cancelAllTaskViewAnimations();

            Task launchTask = mStack.getStackTasks().get(launchTaskIndex);
            EventBus.getDefault().send(new LaunchTaskEvent(getChildViewForTask(launchTask),
                    launchTask, null, INVALID_STACK_ID, false /* screenPinningRequested */));

            MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_LAUNCH_PREVIOUS_TASK,
                    launchTask.key.getComponent().toString());
        }
    }

    public final void onBusEvent(LaunchTaskStartedEvent event) {
        mAnimationHelper.startLaunchTaskAnimation(event.taskView, event.screenPinningRequested,
                event.getAnimationTrigger());
    }

    public final void onBusEvent(DismissRecentsToHomeAnimationStarted event) {
        // Stop any scrolling
        mStackScroller.stopScroller();
        mStackScroller.stopBoundScrollAnimation();

        // Start the task animations
        mAnimationHelper.startExitToHomeAnimation(event.animated, event.getAnimationTrigger());

        // Dismiss the freeform workspace background
        int taskViewExitToHomeDuration = TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION;
        animateFreeformWorkspaceBackgroundAlpha(0, new AnimationProps(taskViewExitToHomeDuration,
                Interpolators.FAST_OUT_SLOW_IN));
    }

    public final void onBusEvent(DismissFocusedTaskViewEvent event) {
        if (mFocusedTask != null) {
            TaskView tv = getChildViewForTask(mFocusedTask);
            if (tv != null) {
                tv.dismissTask();
            }
            resetFocusedTask(mFocusedTask);
        }
    }

    public final void onBusEvent(final DismissTaskViewEvent event) {
        // For visible children, defer removing the task until after the animation
        mAnimationHelper.startDeleteTaskAnimation(event.task, event.taskView,
                event.getAnimationTrigger());
    }

    public final void onBusEvent(TaskViewDismissedEvent event) {
        removeTaskViewFromStack(event.taskView, event.task);
        EventBus.getDefault().send(new DeleteTaskDataEvent(event.task));

        MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_DISMISS,
                event.task.key.getComponent().toString());
    }

    public final void onBusEvent(FocusNextTaskViewEvent event) {
        // Stop any scrolling
        mStackScroller.stopScroller();
        mStackScroller.stopBoundScrollAnimation();

        setRelativeFocusedTask(true, false /* stackTasksOnly */, true /* animated */, false,
                event.timerIndicatorDuration);
    }

    public final void onBusEvent(FocusPreviousTaskViewEvent event) {
        // Stop any scrolling
        mStackScroller.stopScroller();
        mStackScroller.stopBoundScrollAnimation();

        setRelativeFocusedTask(false, false /* stackTasksOnly */, true /* animated */);
    }

    public final void onBusEvent(UserInteractionEvent event) {
        // Poke the doze trigger on user interaction
        mUIDozeTrigger.poke();

        RecentsDebugFlags debugFlags = Recents.getDebugFlags();
        if (debugFlags.isFastToggleRecentsEnabled() && mFocusedTask != null) {
            TaskView tv = getChildViewForTask(mFocusedTask);
            if (tv != null) {
                tv.getHeaderView().cancelFocusTimerIndicator();
            }
        }
    }

    public final void onBusEvent(DragStartEvent event) {
        // Ensure that the drag task is not animated
        addIgnoreTask(event.task);

        if (event.task.isFreeformTask()) {
            // Animate to the front of the stack
            mStackScroller.animateScroll(mLayoutAlgorithm.mInitialScrollP, null);
        }

        // Enlarge the dragged view slightly
        float finalScale = event.taskView.getScaleX() * DRAG_SCALE_FACTOR;
        mLayoutAlgorithm.getStackTransform(event.task, getScroller().getStackScroll(),
                mTmpTransform, null);
        mTmpTransform.scale = finalScale;
        mTmpTransform.translationZ = mLayoutAlgorithm.mMaxTranslationZ + 1;
        updateTaskViewToTransform(event.taskView, mTmpTransform,
                new AnimationProps(DRAG_SCALE_DURATION, Interpolators.FAST_OUT_SLOW_IN));
    }

    public final void onBusEvent(DragStartInitializeDropTargetsEvent event) {
        SystemServicesProxy ssp = Recents.getSystemServices();
        if (ssp.hasFreeformWorkspaceSupport()) {
            event.handler.registerDropTargetForCurrentDrag(mStackDropTarget);
            event.handler.registerDropTargetForCurrentDrag(mFreeformWorkspaceDropTarget);
        }
    }

    public final void onBusEvent(DragDropTargetChangedEvent event) {
        AnimationProps animation = new AnimationProps(250, Interpolators.FAST_OUT_SLOW_IN);
        if (event.dropTarget instanceof TaskStack.DockState) {
            // Calculate the new task stack bounds that matches the window size that Recents will
            // have after the drop
            final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget;
            mStackBounds.set(dockState.getDockedTaskStackBounds(getMeasuredWidth(),
                    getMeasuredHeight(), mDividerSize, mLayoutAlgorithm.mSystemInsets,
                    getResources()));
            mLayoutAlgorithm.initialize(mStackBounds,
                    TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
            updateLayoutAlgorithm(true /* boundScroll */);
        } else {
            // Restore the pre-drag task stack bounds, but ensure that we don't layout the dragging
            // task view, so add it back to the ignore set after updating the layout
            mStackBounds.set(mStableStackBounds);
            removeIgnoreTask(event.task);
            mLayoutAlgorithm.initialize(mStackBounds,
                    TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
            updateLayoutAlgorithm(true /* boundScroll */);
            addIgnoreTask(event.task);
        }
        relayoutTaskViews(animation);
    }

    public final void onBusEvent(final DragEndEvent event) {
        // We don't handle drops on the dock regions
        if (event.dropTarget instanceof TaskStack.DockState) {
            return;
        }

        boolean isFreeformTask = event.task.isFreeformTask();
        boolean hasChangedStacks =
                (!isFreeformTask && event.dropTarget == mFreeformWorkspaceDropTarget) ||
                        (isFreeformTask && event.dropTarget == mStackDropTarget);

        if (hasChangedStacks) {
            // Move the task to the right position in the stack (ie. the front of the stack if
            // freeform or the front of the stack if fullscreen). Note, we MUST move the tasks
            // before we update their stack ids, otherwise, the keys will have changed.
            if (event.dropTarget == mFreeformWorkspaceDropTarget) {
                mStack.moveTaskToStack(event.task, FREEFORM_WORKSPACE_STACK_ID);
            } else if (event.dropTarget == mStackDropTarget) {
                mStack.moveTaskToStack(event.task, FULLSCREEN_WORKSPACE_STACK_ID);
            }
            updateLayoutAlgorithm(true /* boundScroll */);

            // Move the task to the new stack in the system after the animation completes
            event.addPostAnimationCallback(new Runnable() {
                @Override
                public void run() {
                    SystemServicesProxy ssp = Recents.getSystemServices();
                    ssp.moveTaskToStack(event.task.key.id, event.task.key.stackId);
                }
            });
        }

        // We translated the view but we need to animate it back from the current layout-space rect
        // to its final layout-space rect
        int x = (int) event.taskView.getTranslationX();
        int y = (int) event.taskView.getTranslationY();
        Rect taskViewRect = new Rect(event.taskView.getLeft(), event.taskView.getTop(),
                event.taskView.getRight(), event.taskView.getBottom());
        taskViewRect.offset(x, y);
        event.taskView.setTranslationX(0);
        event.taskView.setTranslationY(0);
        event.taskView.setLeftTopRightBottom(taskViewRect.left, taskViewRect.top,
                taskViewRect.right, taskViewRect.bottom);

        // Animate the non-drag TaskViews back into position
        mLayoutAlgorithm.getStackTransform(event.task, getScroller().getStackScroll(),
                mTmpTransform, null);
        event.getAnimationTrigger().increment();
        relayoutTaskViews(new AnimationProps(DEFAULT_SYNC_STACK_DURATION,
                Interpolators.FAST_OUT_SLOW_IN));

        // Animate the drag TaskView back into position
        updateTaskViewToTransform(event.taskView, mTmpTransform,
                new AnimationProps(DEFAULT_SYNC_STACK_DURATION, Interpolators.FAST_OUT_SLOW_IN,
                        event.getAnimationTrigger().decrementOnAnimationEnd()));
        removeIgnoreTask(event.task);
    }

    public final void onBusEvent(IterateRecentsEvent event) {
        if (!mEnterAnimationComplete) {
            // Cancel the previous task's window transition before animating the focused state
            EventBus.getDefault().send(new CancelEnterRecentsWindowAnimationEvent(null));
        }
    }

    public final void onBusEvent(EnterRecentsWindowAnimationCompletedEvent event) {
        mEnterAnimationComplete = true;

        if (mStack.getTaskCount() > 0) {
            // Start the task enter animations
            mAnimationHelper.startEnterAnimation(event.getAnimationTrigger());

            // Add a runnable to the post animation ref counter to clear all the views
            event.addPostAnimationCallback(new Runnable() {
                @Override
                public void run() {
                    // Start the dozer to trigger to trigger any UI that shows after a timeout
                    mUIDozeTrigger.startDozing();

                    // Update the focused state here -- since we only set the focused task without
                    // requesting view focus in onFirstLayout(), actually request view focus and
                    // animate the focused state if we are alt-tabbing now, after the window enter
                    // animation is completed
                    if (mFocusedTask != null) {
                        RecentsConfiguration config = Recents.getConfiguration();
                        RecentsActivityLaunchState launchState = config.getLaunchState();
                        setFocusedTask(mStack.indexOfStackTask(mFocusedTask),
                                false /* scrollToTask */, launchState.launchedWithAltTab);
                    }

                    EventBus.getDefault().send(new EnterRecentsTaskStackAnimationCompletedEvent());
                }
            });
        }
    }

    public final void onBusEvent(UpdateFreeformTaskViewVisibilityEvent event) {
        List<TaskView> taskViews = getTaskViews();
        int taskViewCount = taskViews.size();
        for (int i = 0; i < taskViewCount; i++) {
            TaskView tv = taskViews.get(i);
            Task task = tv.getTask();
            if (task.isFreeformTask()) {
                tv.setVisibility(event.visible ? View.VISIBLE : View.INVISIBLE);
            }
        }
    }

    public final void onBusEvent(ShowHistoryEvent event) {
        ReferenceCountedTrigger postAnimTrigger = new ReferenceCountedTrigger();
        postAnimTrigger.addLastDecrementRunnable(new Runnable() {
            @Override
            public void run() {
                setVisibility(View.INVISIBLE);
            }
        });
        mAnimationHelper.startShowHistoryAnimation(postAnimTrigger);
    }

    public final void onBusEvent(HideHistoryEvent event) {
        setVisibility(View.VISIBLE);
        mAnimationHelper.startHideHistoryAnimation();
    }

    public final void onBusEvent(MultiWindowStateChangedEvent event) {
        if (!event.inMultiWindow) {
            // Scroll the stack to the front to see the undocked task
            mStackScroller.animateScroll(mLayoutAlgorithm.mMaxScrollP, new Runnable() {
                @Override
                public void run() {
                    List<TaskView> taskViews = getTaskViews();
                    int taskViewCount = taskViews.size();
                    for (int i = 0; i < taskViewCount; i++) {
                        TaskView tv = taskViews.get(i);
                        tv.getHeaderView().rebindToTask(tv.getTask(), tv.mTouchExplorationEnabled,
                                tv.mIsDisabledInSafeMode);
                    }
                }
            });
        }
    }

    public final void onBusEvent(ConfigurationChangedEvent event) {
        mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
        mLayoutAlgorithm.initialize(mStackBounds,
                TaskStackLayoutAlgorithm.StackState.getStackStateForStack(mStack));
    }

    /**
     * Removes the task from the stack, and updates the focus to the next task in the stack if the
     * removed TaskView was focused.
     */
    private void removeTaskViewFromStack(TaskView tv, Task task) {
        // Announce for accessibility
        tv.announceForAccessibility(getContext().getString(
                R.string.accessibility_recents_item_dismissed, task.title));

        // Remove the task from the stack
        mStack.removeTask(task, new AnimationProps(DEFAULT_SYNC_STACK_DURATION,
                Interpolators.FAST_OUT_SLOW_IN));
    }

    /**
     * Starts an alpha animation on the freeform workspace background.
     */
    private void animateFreeformWorkspaceBackgroundAlpha(int targetAlpha,
            AnimationProps animation) {
        if (mFreeformWorkspaceBackground.getAlpha() == targetAlpha) {
            return;
        }

        Utilities.cancelAnimationWithoutCallbacks(mFreeformWorkspaceBackgroundAnimator);
        mFreeformWorkspaceBackgroundAnimator = ObjectAnimator.ofInt(mFreeformWorkspaceBackground,
                Utilities.DRAWABLE_ALPHA, mFreeformWorkspaceBackground.getAlpha(), targetAlpha);
        mFreeformWorkspaceBackgroundAnimator.setStartDelay(
                animation.getDuration(AnimationProps.ALPHA));
        mFreeformWorkspaceBackgroundAnimator.setDuration(
                animation.getDuration(AnimationProps.ALPHA));
        mFreeformWorkspaceBackgroundAnimator.setInterpolator(
                animation.getInterpolator(AnimationProps.ALPHA));
        mFreeformWorkspaceBackgroundAnimator.start();
    }

    /**
     * Returns the insert index for the task in the current set of task views. If the given task
     * is already in the task view list, then this method returns the insert index assuming it
     * is first removed at the previous index.
     *
     * @param task the task we are finding the index for
     * @param taskIndex the index of the task in the stack
     */
    private int findTaskViewInsertIndex(Task task, int taskIndex) {
        if (taskIndex != -1) {
            List<TaskView> taskViews = getTaskViews();
            boolean foundTaskView = false;
            int taskViewCount = taskViews.size();
            for (int i = 0; i < taskViewCount; i++) {
                Task tvTask = taskViews.get(i).getTask();
                if (tvTask == task) {
                    foundTaskView = true;
                } else if (taskIndex < mStack.indexOfStackTask(tvTask)) {
                    if (foundTaskView) {
                        return i - 1;
                    } else {
                        return i;
                    }
                }
            }
        }
        return -1;
    }

    /**
     * @return whether the history button should be visible
     */
    private boolean shouldShowHistoryButton() {
        return !mStack.getHistoricalTasks().isEmpty();
    }

    /**
     * Reads current system flags related to accessibility and screen pinning.
     */
    private void readSystemFlags() {
        SystemServicesProxy ssp = Recents.getSystemServices();
        mTouchExplorationEnabled = ssp.isTouchExplorationEnabled();
        mScreenPinningEnabled = ssp.getSystemSetting(getContext(),
                Settings.System.LOCK_TO_APP_ENABLED) != 0;
    }
}
