Merge "Adding scrim to task views. (Bug 15704955)" into lmp-dev
diff --git a/packages/SystemUI/res/layout/recents_task_view.xml b/packages/SystemUI/res/layout/recents_task_view.xml
index 6cfff2e3..828065b 100644
--- a/packages/SystemUI/res/layout/recents_task_view.xml
+++ b/packages/SystemUI/res/layout/recents_task_view.xml
@@ -17,7 +17,8 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent" 
     android:layout_height="match_parent"
-    android:focusable="true">
+    android:focusable="true"
+    android:background="#FFffffff">
     <com.android.systemui.recents.views.TaskViewThumbnail
         android:id="@+id/task_view_thumbnail"
         android:layout_width="match_parent"
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 3db0a2b..bf80d84 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -222,6 +222,9 @@
     <!-- The amount to offset when animating into an affiliate group. -->
     <dimen name="recents_task_view_affiliate_group_enter_offset">64dp</dimen>
 
+    <!-- The alpha to apply to a task thumbnail. -->
+    <item name="recents_task_view_thumbnail_alpha" format="float" type="dimen">0.9</item>
+
     <!-- The height of a task view bar. -->
     <dimen name="recents_task_bar_height">56dp</dimen>
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 3d4d6c4..3709c43 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -39,6 +39,8 @@
             public static final boolean EnableSearchLayout = true;
             // Enables the dynamic shadows behind each task
             public static final boolean EnableShadows = true;
+            // Enables the thumbnail alpha on the front-most task
+            public static final boolean EnableThumbnailAlphaOnFrontmost = false;
             // This disables the bitmap and icon caches
             public static final boolean DisableBackgroundCache = false;
             // Enables the simulated task affiliations
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index 41e06de..7fafe7a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -385,7 +385,7 @@
         // Private API calls to make the shadows look better
         try {
             Utilities.setShadowProperty("ambientShadowStrength", String.valueOf(35f));
-            Utilities.setShadowProperty("ambientRatio", String.valueOf(0.5f));
+            Utilities.setShadowProperty("ambientRatio", String.valueOf(1.5f));
         } catch (IllegalAccessException e) {
             e.printStackTrace();
         } catch (InvocationTargetException e) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 3f5018d..b7f6451 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -81,6 +81,7 @@
     public int taskViewRoundedCornerRadiusPx;
     public int taskViewHighlightPx;
     public int taskViewAffiliateGroupEnterOffsetPx;
+    public float taskViewThumbnailAlpha;
 
     /** Task bar colors */
     public int taskBarViewDefaultBackgroundColor;
@@ -217,6 +218,9 @@
         taskViewTranslationZMaxPx = res.getDimensionPixelSize(R.dimen.recents_task_view_z_max);
         taskViewAffiliateGroupEnterOffsetPx =
                 res.getDimensionPixelSize(R.dimen.recents_task_view_affiliate_group_enter_offset);
+        TypedValue thumbnailAlphaValue = new TypedValue();
+        res.getValue(R.dimen.recents_task_view_thumbnail_alpha, thumbnailAlphaValue, true);
+        taskViewThumbnailAlpha = thumbnailAlphaValue.getFloat();
 
         // Task bar colors
         taskBarViewDefaultBackgroundColor =
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
index 4c0ff48..c87a901 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/ReferenceCountedTrigger.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.recents.misc;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.content.Context;
 
 import java.util.ArrayList;
@@ -98,10 +100,19 @@
         }
     }
 
-    /** Convenience method to decrement this trigger as a runnable */
+    /** Convenience method to decrement this trigger as a runnable. */
     public Runnable decrementAsRunnable() {
         return mDecrementRunnable;
     }
+    /** Convenience method to decrement this trigger as a animator listener. */
+    public Animator.AnimatorListener decrementOnAnimationEnd() {
+        return new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationEnd(Animator animation) {
+                decrement();
+            }
+        };
+    }
 
     /** Returns the current ref count */
     public int getCount() {
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 4fd9136..21b62e9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -73,6 +73,7 @@
     boolean mStackViewsDirty = true;
     boolean mAwaitingFirstLayout = true;
     boolean mStartEnterAnimationRequestedAfterLayout;
+    boolean mStartEnterAnimationCompleted;
     ViewAnimation.TaskViewEnterContext mStartEnterAnimationContext;
     int[] mTmpVisibleRange = new int[2];
     TaskViewTransform mTmpTransform = new TaskViewTransform();
@@ -609,6 +610,7 @@
             ctx.postAnimationTrigger.addLastDecrementRunnable(new Runnable() {
                 @Override
                 public void run() {
+                    mStartEnterAnimationCompleted = true;
                     // Start dozing
                     mUIDozeTrigger.startDozing();
                 }
@@ -814,6 +816,11 @@
             tv.setNoUserInteractionState();
         }
 
+        // If we've finished the start animation, then ensure we always enable the focus animations
+        if (mStartEnterAnimationCompleted) {
+            tv.enableFocusAnimations();
+        }
+
         // Find the index where this task should be placed in the stack
         int insertIndex = -1;
         int taskIndex = mStack.indexOfTask(task);
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 236229e..5914b39 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -17,7 +17,6 @@
 package com.android.systemui.recents.views;
 
 import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
@@ -55,6 +54,7 @@
 
     float mTaskProgress;
     ObjectAnimator mTaskProgressAnimator;
+    ObjectAnimator mDimAnimator;
     float mMaxDimScale;
     int mDim;
     AccelerateInterpolator mDimInterpolator = new AccelerateInterpolator(1.25f);
@@ -222,6 +222,7 @@
      * first layout because the actual animation into recents may take a long time. */
     void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask,
                                              boolean occludesLaunchTarget, int offscreenY) {
+        int initialDim = getDim();
         if (mConfig.launchedFromAppWithScreenshot) {
             if (isTaskViewLaunchTargetTask) {
                 mHeaderView.prepareEnterRecentsAnimation();
@@ -240,7 +241,7 @@
                 // Hide the action button if it exists
                 mActionButtonView.setAlpha(0f);
                 // Set the dim to 0 so we can animate it in
-                setDim(0);
+                initialDim = 0;
             } else if (occludesLaunchTarget) {
                 // Move the task view off screen (below) so we can animate it in
                 setTranslationY(offscreenY);
@@ -255,6 +256,10 @@
             setScaleX(1f);
             setScaleY(1f);
         }
+        // Apply the current dim
+        setDim(initialDim);
+        // Prepare the thumbnail view alpha
+        mThumbnailView.prepareEnterRecentsAnimation(isTaskViewLaunchTargetTask);
     }
 
     /** Animates this task view as it enters recents */
@@ -340,20 +345,24 @@
                 // Animate the task bar of the first task view
                 mHeaderView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay,
                         mThumbnailView.enableTaskBarClipAsRunnable(mHeaderView));
-
-                // Animate the dim into view as well
-                ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", getDimFromTaskProgress());
-                anim.setStartDelay(mConfig.taskBarEnterAnimDelay);
-                anim.setDuration(mConfig.taskBarEnterAnimDuration);
-                anim.setInterpolator(mConfig.fastOutLinearInInterpolator);
-                anim.addListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        // Decrement the post animation trigger
-                        ctx.postAnimationTrigger.decrement();
-                    }
-                });
-                anim.start();
+                // Animate the dim/overlay
+                if (Constants.DebugFlags.App.EnableThumbnailAlphaOnFrontmost) {
+                    // Animate the thumbnail alpha before the dim animation (to prevent updating the
+                    // hardware layer)
+                    mThumbnailView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay,
+                            new Runnable() {
+                                @Override
+                                public void run() {
+                                    animateDimToProgress(0, mConfig.taskBarEnterAnimDuration,
+                                            ctx.postAnimationTrigger.decrementOnAnimationEnd());
+                                }
+                            });
+                } else {
+                    // Immediately start the dim animation
+                    animateDimToProgress(mConfig.taskBarEnterAnimDelay,
+                            mConfig.taskBarEnterAnimDuration,
+                            ctx.postAnimationTrigger.decrementOnAnimationEnd());
+                }
                 ctx.postAnimationTrigger.increment();
 
                 // Animate the footer into view
@@ -459,8 +468,10 @@
     void startLaunchTaskAnimation(final Runnable r, boolean isLaunchingTask,
             boolean occludesLaunchTarget) {
         if (isLaunchingTask) {
-            // Disable the thumbnail clip and animate the bar out
+            // Disable the thumbnail clip and animate the bar out for the window animation out
             mHeaderView.startLaunchTaskAnimation(mThumbnailView.disableTaskBarClipAsRunnable(), r);
+            // Animate the thumbnail alpha back into full opacity for the window animation out
+            mThumbnailView.startLaunchTaskAnimation();
 
             // Animate the dim
             if (mDim > 0) {
@@ -612,10 +623,18 @@
     /** Returns the current dim. */
     public void setDim(int dim) {
         mDim = dim;
-        int inverse = 255 - mDim;
-        mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse));
-        mLayerPaint.setColorFilter(mDimColorFilter);
-        setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint);
+        // Defer setting hardware layers if we have not yet measured, or there is no dim to draw
+        if (getMeasuredWidth() > 0 && getMeasuredHeight() > 0 && dim > 0) {
+            if (mDimAnimator != null) {
+                mDimAnimator.removeAllListeners();
+                mDimAnimator.cancel();
+            }
+
+            int inverse = 255 - mDim;
+            mDimColorFilter.setColor(Color.argb(0xFF, inverse, inverse, inverse));
+            mLayerPaint.setColorFilter(mDimColorFilter);
+            setLayerType(LAYER_TYPE_HARDWARE, mLayerPaint);
+        }
     }
 
     /** Returns the current dim. */
@@ -623,6 +642,21 @@
         return mDim;
     }
 
+    /** Animates the dim to the task progress. */
+    void animateDimToProgress(int delay, int duration, Animator.AnimatorListener postAnimRunnable) {
+        // Animate the dim into view as well
+        int toDim = getDimFromTaskProgress();
+        if (toDim != getDim()) {
+            ObjectAnimator anim = ObjectAnimator.ofInt(TaskView.this, "dim", toDim);
+            anim.setStartDelay(delay);
+            anim.setDuration(duration);
+            if (postAnimRunnable != null) {
+                anim.addListener(postAnimRunnable);
+            }
+            anim.start();
+        }
+    }
+
     /** Compute the dim as a function of the scale of this view. */
     int getDimFromTaskProgress() {
         float dim = mMaxDimScale * mDimInterpolator.getInterpolation(1f - mTaskProgress);
@@ -647,6 +681,8 @@
             // Focus the header bar
             mHeaderView.onTaskViewFocusChanged(true);
         }
+        // Update the thumbnail alpha with the focus
+        mThumbnailView.onFocusChanged(true);
         // Call the callback
         mCb.onTaskViewFocusChanged(this, true);
         // Workaround, we don't always want it focusable in touch mode, but we want the first task
@@ -670,6 +706,8 @@
                 // Un-focus the header bar
                 mHeaderView.onTaskViewFocusChanged(false);
             }
+            // Update the thumbnail alpha with the focus
+            mThumbnailView.onFocusChanged(false);
             // Call the callback
             mCb.onTaskViewFocusChanged(this, false);
             invalidate();
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
index f836aa3..f223bf3 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -21,12 +21,15 @@
 import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.View;
+import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.model.Task;
 
 
 /** The task thumbnail view */
 public class TaskViewThumbnail extends FixedSizeImageView {
 
+    RecentsConfiguration mConfig;
+
     // Task bar clipping
     Rect mClipRect = new Rect();
 
@@ -44,9 +47,15 @@
 
     public TaskViewThumbnail(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+        mConfig = RecentsConfiguration.getInstance();
         setScaleType(ScaleType.FIT_XY);
     }
 
+    @Override
+    protected void onFinishInflate() {
+        setAlpha(0.9f);
+    }
+
     /** Updates the clip rect based on the given task bar. */
     void enableTaskBarClip(View taskBar) {
         int top = (int) Math.max(0, taskBar.getTranslationY() +
@@ -101,4 +110,51 @@
     void unbindFromTask() {
         setImageDrawable(null);
     }
+
+    /** Handles focus changes. */
+    void onFocusChanged(boolean focused) {
+        if (focused) {
+            if (Float.compare(getAlpha(), 1f) != 0) {
+                startFadeAnimation(1f, 0, 150, null);
+            }
+        } else {
+            if (Float.compare(getAlpha(), mConfig.taskViewThumbnailAlpha) != 0) {
+                startFadeAnimation(mConfig.taskViewThumbnailAlpha, 0, 150, null);
+            }
+        }
+    }
+
+    /** Prepares for the enter recents animation. */
+    void prepareEnterRecentsAnimation(boolean isTaskViewLaunchTargetTask) {
+        if (isTaskViewLaunchTargetTask) {
+            setAlpha(1f);
+        } else {
+            setAlpha(mConfig.taskViewThumbnailAlpha);
+        }
+    }
+
+    /** Animates this task thumbnail as it enters recents */
+    void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
+        startFadeAnimation(mConfig.taskViewThumbnailAlpha, delay,
+                mConfig.taskBarEnterAnimDuration, postAnimRunnable);
+    }
+
+    /** Animates this task thumbnail as it exits recents */
+    void startLaunchTaskAnimation() {
+        startFadeAnimation(1f, 0, mConfig.taskBarExitAnimDuration, null);
+    }
+
+    /** Animates the thumbnail alpha. */
+    void startFadeAnimation(float finalAlpha, int delay, int duration, Runnable postAnimRunnable) {
+        if (postAnimRunnable != null) {
+            animate().withEndAction(postAnimRunnable);
+        }
+        animate()
+                .alpha(finalAlpha)
+                .setStartDelay(delay)
+                .setInterpolator(mConfig.fastOutSlowInInterpolator)
+                .setDuration(duration)
+                .withLayer()
+                .start();
+    }
 }
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 0e1340c..f6ec86d 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -159,7 +159,7 @@
     private final int mConfigShortAnimTime;
     private final Interpolator mDecelerateInterpolator;
     private final Interpolator mThumbnailFadeoutInterpolator;
-    private final Interpolator mThumbnailCubicInterpolator;
+    private final Interpolator mThumbnailFastOutSlowInInterpolator;
 
     private int mCurrentUserId = 0;
 
@@ -170,7 +170,7 @@
                 com.android.internal.R.integer.config_shortAnimTime);
         mDecelerateInterpolator = AnimationUtils.loadInterpolator(context,
                 com.android.internal.R.interpolator.decelerate_cubic);
-        mThumbnailCubicInterpolator = AnimationUtils.loadInterpolator(context,
+        mThumbnailFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
                 com.android.internal.R.interpolator.fast_out_slow_in);
         mThumbnailFadeoutInterpolator = new Interpolator() {
             @Override
@@ -635,7 +635,7 @@
         }
 
         return prepareThumbnailAnimationWithDuration(a, appWidth, appHeight,
-                THUMBNAIL_APP_TRANSITION_DURATION, mThumbnailCubicInterpolator);
+                THUMBNAIL_APP_TRANSITION_DURATION, mThumbnailFastOutSlowInInterpolator);
     }
 
     /**