am 7c04ca66: am 96af21df: am 86bb7f0a: Merge "Fixing issue with the lock-to-app setting not being refreshed when entering recents." into lmp-dev

* commit '7c04ca66712edf78024156c452287fccefde8479':
  Fixing issue with the lock-to-app setting not being refreshed when entering recents.
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 85668de..93c5538 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -67,8 +67,7 @@
         android:layout_width="match_parent"
         android:layout_height="@dimen/recents_task_view_lock_to_app_button_height"
         android:layout_gravity="center_horizontal|bottom"
-        android:background="@drawable/recents_lock_to_task_button_bg"
-        android:visibility="invisible">
+        android:background="@drawable/recents_lock_to_task_button_bg">
         <TextView
             android:layout_width="wrap_content"
             android:layout_height="match_parent"
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 7d69b94..18dad3a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -431,6 +431,9 @@
         super.onNewIntent(intent);
         setIntent(intent);
 
+        // Reinitialize the configuration
+        RecentsConfiguration.reinitialize(this, RecentsTaskLoader.getInstance().getSystemServicesProxy());
+
         // Clear any debug rects
         if (mDebugOverlay != null) {
             mDebugOverlay.clear();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 55711cf0..bffc230 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -305,6 +305,11 @@
                 (!transposeRecentsLayoutWithOrientation || !isLandscape);
     }
 
+    /** Returns whether the current layout is horizontal. */
+    public boolean hasHorizontalLayout() {
+        return isLandscape && transposeRecentsLayoutWithOrientation;
+    }
+
     /**
      * Returns the task stack bounds in the current orientation. These bounds do not account for
      * the system insets.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
index 9076818..34f73c6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/AnimateableViewBounds.java
@@ -17,6 +17,7 @@
 package com.android.systemui.recents.views;
 
 import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
 import android.graphics.Outline;
 import android.graphics.Rect;
 import android.view.View;
@@ -34,6 +35,7 @@
     int mCornerRadius;
 
     ObjectAnimator mClipTopAnimator;
+    ObjectAnimator mClipRightAnimator;
     ObjectAnimator mClipBottomAnimator;
 
     public AnimateableViewBounds(View source, int cornerRadius) {
@@ -42,6 +44,7 @@
         mCornerRadius = cornerRadius;
         mSourceView.setClipToOutline(true);
         setClipTop(getClipTop());
+        setClipRight(getClipRight());
         setClipBottom(getClipBottom());
         setOutlineClipBottom(getOutlineClipBottom());
     }
@@ -56,7 +59,7 @@
     }
 
     /** Animates the top clip. */
-    void animateClipTop(int top, int duration) {
+    void animateClipTop(int top, int duration, ValueAnimator.AnimatorUpdateListener updateListener) {
         if (mClipTopAnimator != null) {
             mClipTopAnimator.removeAllListeners();
             mClipTopAnimator.cancel();
@@ -64,6 +67,9 @@
         mClipTopAnimator = ObjectAnimator.ofInt(this, "clipTop", top);
         mClipTopAnimator.setDuration(duration);
         mClipTopAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
+        if (updateListener != null) {
+            mClipTopAnimator.addUpdateListener(updateListener);
+        }
         mClipTopAnimator.start();
     }
 
@@ -80,16 +86,41 @@
         return mClipRect.top;
     }
 
+    /** Animates the right clip. */
+    void animateClipRight(int right, int duration) {
+        if (mClipRightAnimator != null) {
+            mClipRightAnimator.removeAllListeners();
+            mClipRightAnimator.cancel();
+        }
+        mClipRightAnimator = ObjectAnimator.ofInt(this, "clipRight", right);
+        mClipRightAnimator.setDuration(duration);
+        mClipRightAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
+        mClipRightAnimator.start();
+    }
+
+    /** Sets the right clip. */
+    public void setClipRight(int right) {
+        if (right != mClipRect.right) {
+            mClipRect.right = right;
+            mSourceView.invalidateOutline();
+        }
+    }
+
+    /** Returns the right clip. */
+    public int getClipRight() {
+        return mClipRect.right;
+    }
+
     /** Animates the bottom clip. */
     void animateClipBottom(int bottom, int duration) {
-        if (mClipTopAnimator != null) {
-            mClipTopAnimator.removeAllListeners();
-            mClipTopAnimator.cancel();
+        if (mClipBottomAnimator != null) {
+            mClipBottomAnimator.removeAllListeners();
+            mClipBottomAnimator.cancel();
         }
-        mClipTopAnimator = ObjectAnimator.ofInt(this, "clipBottom", bottom);
-        mClipTopAnimator.setDuration(duration);
-        mClipTopAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
-        mClipTopAnimator.start();
+        mClipBottomAnimator = ObjectAnimator.ofInt(this, "clipBottom", bottom);
+        mClipBottomAnimator.setDuration(duration);
+        mClipBottomAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
+        mClipBottomAnimator.start();
     }
 
     /** Sets the bottom clip. */
@@ -105,6 +136,7 @@
         return mClipRect.bottom;
     }
 
+    /** Sets the outline bottom clip. */
     public void setOutlineClipBottom(int bottom) {
         if (bottom != mOutlineClipRect.bottom) {
             mOutlineClipRect.bottom = bottom;
@@ -112,6 +144,7 @@
         }
     }
 
+    /** Gets the outline bottom clip. */
     public int getOutlineClipBottom() {
         return mOutlineClipRect.bottom;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java
index 95af1c9..881bbcf 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskFooterView.java
@@ -16,12 +16,9 @@
 
 package com.android.systemui.recents.views;
 
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.util.AttributeSet;
-import android.view.View;
 import android.widget.FrameLayout;
 import com.android.systemui.recents.RecentsConfiguration;
 
@@ -82,9 +79,6 @@
     void animateFooterVisibility(final boolean visible, int duration) {
         // Return early if there is no footer
         if (mMaxFooterHeight <= 0) return;
-        // Return early if we are already in the final state
-        if (!visible && getVisibility() != View.VISIBLE) return;
-        if (visible && getVisibility() == View.VISIBLE) return;
 
         // Cancel the previous animation
         if (mFooterAnimator != null) {
@@ -93,25 +87,12 @@
         }
         int finalHeight = visible ? mMaxFooterHeight : 0;
         if (duration > 0) {
-            // Make the view visible for the animation
-            if (visible && getVisibility() != View.VISIBLE) {
-                setVisibility(View.VISIBLE);
-            }
             mFooterAnimator = ObjectAnimator.ofInt(this, "footerHeight", finalHeight);
             mFooterAnimator.setDuration(duration);
             mFooterAnimator.setInterpolator(mConfig.fastOutSlowInInterpolator);
-            mFooterAnimator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    if (!visible) {
-                        setVisibility(View.INVISIBLE);
-                    }
-                }
-            });
             mFooterAnimator.start();
         } else {
             setFooterHeight(finalHeight);
-            setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
         }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index f135e32..b501f7e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -83,7 +83,6 @@
     int mFocusedTaskIndex = -1;
     OverScroller mScroller;
     ObjectAnimator mScrollAnimator;
-    boolean mEnableStackClipping = true;
 
     // Optimizations
     ReferenceCountedTrigger mHwLayersTrigger;
@@ -93,8 +92,6 @@
     boolean mStartEnterAnimationRequestedAfterLayout;
     ViewAnimation.TaskViewEnterContext mStartEnterAnimationContext;
     int[] mTmpVisibleRange = new int[2];
-    Rect mTmpRect = new Rect();
-    Rect mTmpRect2 = new Rect();
     TaskViewTransform mTmpTransform = new TaskViewTransform();
     HashMap<Task, TaskView> mTmpTaskViewMap = new HashMap<Task, TaskView>();
     LayoutInflater mInflater;
@@ -189,7 +186,7 @@
                                        int stackScroll,
                                        int[] visibleRangeOut,
                                        boolean boundTranslationsToRect) {
-        // XXX: We should be intelligent about wheee to look for the visible stack range using the
+        // XXX: We should be intelligent about where to look for the visible stack range using the
         //      current stack scroll.
         // XXX: We should log extra cases like the ones below where we don't expect to hit very often
         // XXX: Print out approximately how many indices we have to go through to find the first visible transform
@@ -199,8 +196,6 @@
         int frontMostVisibleIndex = -1;
         int backMostVisibleIndex = -1;
 
-
-
         // We can reuse the task transforms where possible to reduce object allocation
         if (taskTransformCount < taskCount) {
             // If there are less transforms than tasks, then add as many transforms as necessary
@@ -290,6 +285,7 @@
 
                 if (tv == null) {
                     tv = mViewPool.pickUpViewFromPool(task, task);
+
                     if (mStackViewsAnimationDuration > 0) {
                         // For items in the list, put them in start animating them from the
                         // approriate ends of the list where they are expected to appear
@@ -319,7 +315,7 @@
     /** Updates the clip for each of the task views. */
     void clipTaskViews() {
         // Update the clip on each task child
-        if (Constants.DebugFlags.App.EnableTaskStackClipping && mEnableStackClipping) {
+        if (Constants.DebugFlags.App.EnableTaskStackClipping) {
             int childCount = getChildCount();
             for (int i = 0; i < childCount - 1; i++) {
                 TaskView tv = (TaskView) getChildAt(i);
@@ -341,12 +337,10 @@
                     // stacked and we can make assumptions about the visibility of the this
                     // task relative to the ones in front of it.
                     if (nextTv != null) {
-                        // We calculate the bottom clip independent of the footer (since we animate
-                        // that)
-                        int scaledMaxFooterHeight = (int) (tv.getMaxFooterHeight() * tv.getScaleX());
-                        tv.getHitRect(mTmpRect);
-                        nextTv.getHitRect(mTmpRect2);
-                        clipBottom = (mTmpRect.bottom - scaledMaxFooterHeight - mTmpRect2.top);
+                        // We can reuse the current task transforms to find the task rects
+                        TaskViewTransform transform = mCurrentTaskTransforms.get(mStack.indexOfTask(tv.getTask()));
+                        TaskViewTransform nextTransform = mCurrentTaskTransforms.get(mStack.indexOfTask(nextTv.getTask()));
+                        clipBottom = transform.rect.bottom - nextTransform.rect.top - 200;
                     }
                 }
                 tv.getViewBounds().setClipBottom(clipBottom);
@@ -359,18 +353,6 @@
         }
     }
 
-    /** Enables/Disables clipping of the tasks in the stack. */
-    void setStackClippingEnabled(boolean stackClippingEnabled) {
-        if (!stackClippingEnabled) {
-            int childCount = getChildCount();
-            for (int i = 0; i < childCount; i++) {
-                TaskView tv = (TaskView) getChildAt(i);
-                tv.getViewBounds().setClipBottom(0);
-            }
-        }
-        mEnableStackClipping = stackClippingEnabled;
-    }
-
     /** The stack insets to apply to the stack contents */
     public void setStackInsetRect(Rect r) {
         mTaskStackBounds.set(r);
@@ -634,18 +616,6 @@
             setStackScrollToInitialState();
             requestSynchronizeStackViewsWithModel();
             synchronizeStackViewsWithModel();
-
-            // Find the first task and mark it as full screen
-            if (mConfig.launchedFromAppWithScreenshot) {
-                int childCount = getChildCount();
-                for (int i = 0; i < childCount; i++) {
-                    TaskView tv = (TaskView) getChildAt(i);
-                    if (tv.getTask().isLaunchTarget) {
-                        tv.setIsFullScreen(true);
-                        break;
-                    }
-                }
-            }
         }
 
         // Measure each of the TaskViews
@@ -925,6 +895,15 @@
     public void prepareViewToLeavePool(TaskView tv, Task task, boolean isNewView) {
         // Rebind the task and request that this task's data be filled into the TaskView
         tv.onTaskBound(task);
+
+        // Mark the launch task as fullscreen
+        if (Constants.DebugFlags.App.EnableScreenshotAppTransition && mAwaitingFirstLayout) {
+            if (task.isLaunchTarget) {
+                tv.setIsFullScreen(true);
+            }
+        }
+
+        // Load the task data
         RecentsTaskLoader.getInstance().loadTaskData(task);
 
         // Sanity check, the task view should always be clipping against the stack at this point,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
index 7f94a0a..0fd4e86 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewLayoutAlgorithm.java
@@ -82,7 +82,7 @@
         // Compute the min and max scroll values
         int numTasks = Math.max(1, tasks.size());
         int taskHeight = mTaskRect.height();
-        int stackHeight = mStackRect.height();
+        int stackHeight = mStackRectSansPeek.height();
 
         if (numTasks <= 1) {
             // If there is only one task, then center the task in the stack rect (sans peek)
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index b83f9cc..b1c35f3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -263,7 +263,6 @@
                 int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
 
                 if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
-                    // XXX: Make this animation a function of the velocity AND distance
                     int overscrollRange = (int) (Math.min(1f,
                             Math.abs((float) velocity / mMaximumVelocity)) *
                             Constants.Values.TaskStackView.TaskStackOverscrollRange);
@@ -277,7 +276,6 @@
                     mSv.invalidate(mSv.mStackAlgorithm.mStackRect);
                 } else if (mSv.isScrollOutOfBounds()) {
                     // Animate the scroll back into bounds
-                    // XXX: Make this animation a function of the velocity OR distance
                     mSv.animateBoundScroll();
                 }
 
@@ -303,7 +301,6 @@
             case MotionEvent.ACTION_CANCEL: {
                 if (mSv.isScrollOutOfBounds()) {
                     // Animate the scroll back into bounds
-                    // XXX: Make this animation a function of the velocity OR distance
                     mSv.animateBoundScroll();
                 }
                 mActivePointerId = INACTIVE_POINTER_ID;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 259706b..1b5ad6e 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -21,7 +21,6 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
-import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
 import android.graphics.PorterDuff;
@@ -60,7 +59,6 @@
     boolean mTaskDataLoaded;
     boolean mIsFocused;
     boolean mIsFullScreenView;
-    boolean mIsStub;
     boolean mClipViewInStack;
     AnimateableViewBounds mViewBounds;
     Paint mLayerPaint = new Paint();
@@ -123,7 +121,11 @@
         mBarView = (TaskBarView) findViewById(R.id.task_view_bar);
         mThumbnailView = (TaskThumbnailView) findViewById(R.id.task_view_thumbnail);
         mFooterView = (TaskFooterView) findViewById(R.id.lock_to_app);
-        mFooterView.setCallbacks(this);
+        if (mConfig.lockToAppEnabled) {
+            mFooterView.setCallbacks(this);
+        } else {
+            mFooterView.setVisibility(View.GONE);
+        }
     }
 
     @Override
@@ -147,6 +149,7 @@
                     MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY));
         }
         setMeasuredDimension(width, height);
+        invalidateOutline();
     }
 
     /** Synchronizes this view's properties with the task's transform */
@@ -201,9 +204,9 @@
         if (mConfig.launchedFromAppWithScreenshot) {
             if (isTaskViewLaunchTargetTask) {
                 // Also hide the front most task bar view so we can animate it in
-                mBarView.prepareEnterRecentsAnimation();
+                // mBarView.prepareEnterRecentsAnimation();
             } else {
-                // Don't do anything for the side views
+                // Don't do anything for the side views when animating in
             }
 
         } else if (mConfig.launchedFromAppWithThumbnail) {
@@ -232,17 +235,32 @@
 
         if (mConfig.launchedFromAppWithScreenshot) {
             if (mTask.isLaunchTarget) {
-                // XXX: We would have to animate the trasnlationY of the task view bar along with the clip and
-                // reset it at the bottom
+                int duration = mConfig.taskViewEnterFromHomeDuration * 5;
+                int windowInsetTop = mConfig.systemInsets.top; // XXX: Should be for the window
+                float taskScale = ((float) taskRect.width() / getMeasuredWidth()) * transform.scale;
+                float taskTranslationY = taskRect.top + transform.translationY - windowInsetTop;
 
-                // XXX: This should actually be the inset on the current app...
-                mViewBounds.animateClipTop(taskRect.top, mConfig.taskViewEnterFromHomeDuration * 5);
-                mViewBounds.animateClipBottom(getMeasuredHeight() - taskRect.bottom, mConfig.taskViewEnterFromHomeDuration * 5);
-
-                animate().scaleX(((float) taskRect.width() / getMeasuredWidth()) * transform.scale)
-                        .scaleY(((float) taskRect.width() / getMeasuredWidth()) * transform.scale)
-                        .translationY(taskRect.top + transform.translationY)
-                        .setDuration(mConfig.taskViewEnterFromHomeDuration * 5)
+                // Animate the top clip
+                mViewBounds.animateClipTop(windowInsetTop, duration,
+                        new ValueAnimator.AnimatorUpdateListener() {
+                    @Override
+                    public void onAnimationUpdate(ValueAnimator animation) {
+                        int y = (Integer) animation.getAnimatedValue();
+                        mBarView.setTranslationY(y);
+                    }
+                });
+                // Animate the bottom or right clip
+                int size = Math.round((taskRect.width() / taskScale));
+                if (mConfig.hasHorizontalLayout()) {
+                    mViewBounds.animateClipRight(getMeasuredWidth() - size, duration);
+                } else {
+                    mViewBounds.animateClipBottom(getMeasuredHeight() - (windowInsetTop + size), duration);
+                }
+                animate()
+                        .scaleX(taskScale)
+                        .scaleY(taskScale)
+                        .translationY(taskTranslationY)
+                        .setDuration(duration)
                         .withEndAction(new Runnable() {
                             @Override
                             public void run() {
@@ -424,11 +442,6 @@
         return mIsFullScreenView;
     }
 
-    /** Sets the stubbed state of this task view. */
-    void setStubState(boolean isStub) {
-        mIsStub = isStub;
-    }
-
     /**
      * Returns whether this view should be clipped, or any views below should clip against this
      * view.
@@ -447,7 +460,11 @@
 
     /** Gets the max footer height. */
     public int getMaxFooterHeight() {
-        return mFooterView.mMaxFooterHeight;
+        if (mConfig.lockToAppEnabled) {
+            return mFooterView.mMaxFooterHeight;
+        } else {
+            return 0;
+        }
     }
 
     /** Animates the footer into and out of view. */
@@ -488,17 +505,6 @@
         setDim(getDimOverlayFromScale());
     }
 
-    /**** View drawing ****/
-
-    @Override
-    protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
-        if (mIsStub && (child != mBarView)) {
-            // Skip the thumbnail view if we are in stub mode
-            return false;
-        }
-        return super.drawChild(canvas, child, drawingTime);
-    }
-
     /**** View focus state ****/
 
     /**