Simplifying the task header highlight drawing.

- Removed unused ripple logic in the task header background, simplifying
  the background and highlight drawing
- Calculating the header highlight from the actual task color now
- Preventing some extra work from happening when the task view size
  changes

Change-Id: I775651f4b9ce8c1cdfa6fb3d77fd6912fd99a93b
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 0ccc236..905da13 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -62,8 +62,6 @@
     <color name="recents_task_bar_light_icon_color">#ffeeeeee</color>
     <!-- The recents task bar dark dismiss icon color to be drawn on top of light backgrounds. -->
     <color name="recents_task_bar_dark_icon_color">#99000000</color>
-    <!-- The recents task bar highlight color. -->
-    <color name="recents_task_bar_highlight_color">#28ffffff</color>
     <!-- The lock to task button background color. -->
     <color name="recents_task_view_lock_to_app_button_background_color">#ffe6e6e6</color>
     <!-- The lock to task button foreground color. -->
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 035f564..097c352 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -198,16 +198,16 @@
     <dimen name="recents_task_view_rounded_corners_radius">2dp</dimen>
 
     <!-- The min translation in the Z index for the last task. -->
-    <dimen name="recents_task_view_z_min">20dp</dimen>
+    <dimen name="recents_task_view_z_min">16dp</dimen>
 
     <!-- The max translation in the Z index for the last task. -->
-    <dimen name="recents_task_view_z_max">80dp</dimen>
+    <dimen name="recents_task_view_z_max">48dp</dimen>
 
     <!-- The amount to translate when animating the removal of a task. -->
     <dimen name="recents_task_view_remove_anim_translation_x">100dp</dimen>
 
     <!-- The amount of highlight to make on each task view. -->
-    <dimen name="recents_task_view_highlight">1.5dp</dimen>
+    <dimen name="recents_task_view_highlight">1dp</dimen>
 
     <!-- The amount to offset when animating into an affiliate group. -->
     <dimen name="recents_task_view_affiliate_group_enter_offset">64dp</dimen>
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 b09504e..bc441b2 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -200,8 +200,10 @@
     @Override
     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
         super.onSizeChanged(w, h, oldw, oldh);
-        mHeaderView.onTaskViewSizeChanged(w, h);
-        mThumbnailView.onTaskViewSizeChanged(w, h);
+        if (w > 0 && h > 0) {
+            mHeaderView.onTaskViewSizeChanged(w, h);
+            mThumbnailView.onTaskViewSizeChanged(w, h);
+        }
     }
 
     @Override
@@ -378,7 +380,7 @@
         } else {
             float dimAlpha = mDimAlpha / 255.0f;
             mThumbnailView.setDimAlpha(dimAlpha);
-            mHeaderView.setDimAlpha(dim);
+            mHeaderView.setDimAlpha(dimAlpha);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
index e8b7574..6a47424 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewHeader.java
@@ -16,18 +16,18 @@
 
 package com.android.systemui.recents.views;
 
+import android.annotation.Nullable;
 import android.content.Context;
-import android.content.res.ColorStateList;
+import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.ColorFilter;
 import android.graphics.Paint;
-import android.graphics.PorterDuff;
-import android.graphics.PorterDuffXfermode;
+import android.graphics.PixelFormat;
 import android.graphics.Rect;
-import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
-import android.graphics.drawable.GradientDrawable;
 import android.graphics.drawable.RippleDrawable;
+import android.support.v4.graphics.ColorUtils;
 import android.util.AttributeSet;
 import android.view.View;
 import android.view.animation.AnimationUtils;
@@ -36,6 +36,7 @@
 import android.widget.ImageView;
 import android.widget.TextView;
 import com.android.internal.logging.MetricsLogger;
+
 import com.android.systemui.R;
 import com.android.systemui.recents.Constants;
 import com.android.systemui.recents.Recents;
@@ -55,6 +56,66 @@
 public class TaskViewHeader extends FrameLayout
         implements View.OnClickListener, View.OnLongClickListener {
 
+    private static final float HIGHLIGHT_LIGHTNESS_INCREMENT = 0.125f;
+
+    /**
+     * A color drawable that draws a slight highlight at the top to help it stand out.
+     */
+    private class HighlightColorDrawable extends Drawable {
+
+        private Paint mHighlightPaint = new Paint();
+        private Paint mBackgroundPaint = new Paint();
+
+        private float[] mTmpHSL = new float[3];
+
+        public HighlightColorDrawable() {
+            mBackgroundPaint.setColor(Color.argb(255, 0, 0, 0));
+            mBackgroundPaint.setAntiAlias(true);
+            mHighlightPaint.setColor(Color.argb(255, 255, 255, 255));
+            mHighlightPaint.setAntiAlias(true);
+        }
+
+        public void setColorAndDim(int color, float dimAlpha) {
+            mBackgroundPaint.setColor(color);
+
+            ColorUtils.colorToHSL(color, mTmpHSL);
+            // TODO: Consider using the saturation of the color to adjust the lightness as well
+            mTmpHSL[2] = Math.min(1f,
+                    mTmpHSL[2] + HIGHLIGHT_LIGHTNESS_INCREMENT * (1.0f - dimAlpha));
+            mHighlightPaint.setColor(ColorUtils.HSLToColor(mTmpHSL));
+
+            invalidateSelf();
+        }
+
+        @Override
+        public void setColorFilter(@Nullable ColorFilter colorFilter) {
+            // Do nothing
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+            // Do nothing
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            // Draw the highlight at the top edge (but put the bottom edge just out of view)
+            canvas.drawRoundRect(0, 0, mTaskViewRect.width(),
+                    2 * Math.max(mHighlightHeight, mCornerRadius),
+                    mCornerRadius, mCornerRadius, mHighlightPaint);
+
+            // Draw the background with the rounded corners
+            canvas.drawRoundRect(0, mHighlightHeight, mTaskViewRect.width(),
+                    getHeight() + mCornerRadius,
+                    mCornerRadius, mCornerRadius, mBackgroundPaint);
+        }
+
+        @Override
+        public int getOpacity() {
+            return PixelFormat.OPAQUE;
+        }
+    }
+
     Task mTask;
 
     // Header views
@@ -68,17 +129,18 @@
     Rect mTaskViewRect = new Rect();
     int mCornerRadius;
     int mHighlightHeight;
+    float mDimAlpha;
     Drawable mLightDismissDrawable;
     Drawable mDarkDismissDrawable;
-    RippleDrawable mBackground;
-    GradientDrawable mBackgroundColorDrawable;
+    int mTaskBarViewLightTextColor;
+    int mTaskBarViewDarkTextColor;
     String mDismissContentDescription;
 
-    // Static highlight that we draw at the top of each view
-    static Paint sHighlightPaint;
+    // Header background
+    private HighlightColorDrawable mBackground;
 
     // Header dim, which is only used when task view hardware layers are not used
-    Paint mDimLayerPaint = new Paint();
+    private Paint mDimLayerPaint = new Paint();
 
     Interpolator mFastOutSlowInInterpolator;
     Interpolator mFastOutLinearInInterpolator;
@@ -100,29 +162,26 @@
         setWillNotDraw(false);
 
         // Load the dismiss resources
-        mDimLayerPaint.setColor(Color.argb(0, 0, 0, 0));
+        Resources res = context.getResources();
         mLightDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_light);
         mDarkDismissDrawable = context.getDrawable(R.drawable.recents_dismiss_dark);
-        mDismissContentDescription =
-                context.getString(R.string.accessibility_recents_item_will_be_dismissed);
-        mCornerRadius = getResources().getDimensionPixelSize(
-                R.dimen.recents_task_view_rounded_corners_radius);
-        mHighlightHeight = getResources().getDimensionPixelSize(
-                R.dimen.recents_task_view_highlight);
+        mDismissContentDescription = context.getString(
+                R.string.accessibility_recents_item_will_be_dismissed);
+        mCornerRadius = res.getDimensionPixelSize(R.dimen.recents_task_view_rounded_corners_radius);
+        mHighlightHeight = res.getDimensionPixelSize(R.dimen.recents_task_view_highlight);
+        mTaskBarViewLightTextColor = context.getColor(R.color.recents_task_bar_light_text_color);
+        mTaskBarViewDarkTextColor = context.getColor(R.color.recents_task_bar_dark_text_color);
         mFastOutSlowInInterpolator = AnimationUtils.loadInterpolator(context,
                 com.android.internal.R.interpolator.fast_out_slow_in);
         mFastOutLinearInInterpolator = AnimationUtils.loadInterpolator(context,
                 com.android.internal.R.interpolator.fast_out_linear_in);
 
-        // Configure the highlight paint
-        if (sHighlightPaint == null) {
-            sHighlightPaint = new Paint();
-            sHighlightPaint.setStyle(Paint.Style.STROKE);
-            sHighlightPaint.setStrokeWidth(mHighlightHeight);
-            sHighlightPaint.setColor(context.getColor(R.color.recents_task_bar_highlight_color));
-            sHighlightPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.ADD));
-            sHighlightPaint.setAntiAlias(true);
-        }
+        // Configure the background and dim
+        mBackground = new HighlightColorDrawable();
+        mBackground.setColorAndDim(Color.argb(255, 0, 0, 0), 0f);
+        setBackground(mBackground);
+        mDimLayerPaint.setColor(Color.argb(255, 0, 0, 0));
+        mDimLayerPaint.setAntiAlias(true);
     }
 
     @Override
@@ -139,16 +198,6 @@
         if (mIconView.getBackground() instanceof RippleDrawable) {
             mIconView.setBackground(null);
         }
-
-        mBackgroundColorDrawable = (GradientDrawable) getContext().getDrawable(
-                R.drawable.recents_task_view_header_bg_color);
-        // Copy the ripple drawable since we are going to be manipulating it
-        mBackground = (RippleDrawable)
-                getContext().getDrawable(R.drawable.recents_task_view_header_bg);
-        mBackground = (RippleDrawable) mBackground.mutate().getConstantState().newDrawable();
-        mBackground.setColor(ColorStateList.valueOf(0));
-        mBackground.setDrawableByLayerId(mBackground.getId(0), mBackgroundColorDrawable);
-        setBackground(mBackground);
     }
 
     /**
@@ -156,6 +205,11 @@
      * to match the frame changes.
      */
     public void onTaskViewSizeChanged(int width, int height) {
+        // Return early if the bounds have not changed
+        if (mTaskViewRect.width() == width && mTaskViewRect.height() == height) {
+            return;
+        }
+
         mTaskViewRect.set(0, 0, width, height);
         boolean updateMoveTaskButton = mMoveTaskButton.getVisibility() != View.GONE;
         int appIconWidth = mIconView.getMeasuredWidth();
@@ -201,31 +255,39 @@
     }
 
     @Override
-    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
-        onTaskViewSizeChanged(mTaskViewRect.width(), mTaskViewRect.height());
+    protected boolean verifyDrawable(Drawable who) {
+        return super.verifyDrawable(who) || (who == mBackground);
     }
 
     @Override
-    protected void onDraw(Canvas canvas) {
-        // Draw the highlight at the top edge (but put the bottom edge just out of view)
-        float offset = (float) Math.ceil(mHighlightHeight / 2f);
-        float radius = mCornerRadius;
-        int count = canvas.save(Canvas.CLIP_SAVE_FLAG);
-        canvas.clipRect(0, 0, mTaskViewRect.width(), getMeasuredHeight());
-        canvas.drawRoundRect(-offset, 0f, (float) mTaskViewRect.width() + offset,
-                getMeasuredHeight() + radius, radius, radius, sHighlightPaint);
-        canvas.restoreToCount(count);
+    protected void dispatchDraw(Canvas canvas) {
+        super.dispatchDraw(canvas);
+
+        // Draw the dim layer with the rounded corners
+        canvas.drawRoundRect(0, 0, mTaskViewRect.width(), getHeight() + mCornerRadius,
+                mCornerRadius, mCornerRadius, mDimLayerPaint);
     }
 
     /**
      * Sets the dim alpha, only used when we are not using hardware layers.
      * (see RecentsConfiguration.useHardwareLayers)
      */
-    void setDimAlpha(int alpha) {
-        mDimLayerPaint.setColor(Color.argb(alpha, 0, 0, 0));
+    void setDimAlpha(float dimAlpha) {
+        mDimAlpha = dimAlpha;
+        updateBackgroundColor(dimAlpha);
         invalidate();
     }
 
+    /**
+     * Updates the background and highlight colors for this header.
+     */
+    private void updateBackgroundColor(float dimAlpha) {
+        if (mTask != null) {
+            mBackground.setColorAndDim(mTask.colorPrimary, dimAlpha);
+            mDimLayerPaint.setAlpha((int) (dimAlpha * 255));
+        }
+    }
+
     /** Binds the bar view to the task */
     public void rebindToTask(Task t) {
         SystemServicesProxy ssp = Recents.getSystemServices();
@@ -233,6 +295,7 @@
 
         // If an activity icon is defined, then we use that as the primary icon to show in the bar,
         // otherwise, we fall back to the application icon
+        updateBackgroundColor(mDimAlpha);
         if (t.icon != null) {
             mIconView.setImageDrawable(t.icon);
         }
@@ -240,20 +303,8 @@
             mTitleView.setText(t.title);
         }
         mTitleView.setContentDescription(t.contentDescription);
-
-        // Try and apply the system ui tint
-        int existingBgColor = (getBackground() instanceof ColorDrawable) ?
-                ((ColorDrawable) getBackground()).getColor() : 0;
-        if (existingBgColor != t.colorPrimary) {
-            mBackgroundColorDrawable.setColor(t.colorPrimary);
-        }
-
-        int taskBarViewLightTextColor = getResources().getColor(
-                R.color.recents_task_bar_light_text_color);
-        int taskBarViewDarkTextColor = getResources().getColor(
-                R.color.recents_task_bar_dark_text_color);
         mTitleView.setTextColor(t.useLightOnPrimaryColor ?
-                taskBarViewLightTextColor : taskBarViewDarkTextColor);
+                mTaskBarViewLightTextColor : mTaskBarViewDarkTextColor);
         mDismissButton.setImageDrawable(t.useLightOnPrimaryColor ?
                 mLightDismissDrawable : mDarkDismissDrawable);
         mDismissButton.setContentDescription(String.format(mDismissContentDescription,
@@ -273,7 +324,9 @@
                         ? R.drawable.recents_move_task_freeform_light
                         : R.drawable.recents_move_task_freeform_dark);
             }
-            mMoveTaskButton.setVisibility(View.VISIBLE);
+            if (mMoveTaskButton.getVisibility() != View.VISIBLE) {
+                mMoveTaskButton.setVisibility(View.VISIBLE);
+            }
             mMoveTaskButton.setOnClickListener(this);
         }
 
@@ -329,15 +382,6 @@
     }
 
     @Override
-    protected void dispatchDraw(Canvas canvas) {
-        super.dispatchDraw(canvas);
-
-        // Draw the dim layer with the rounded corners
-        canvas.drawRoundRect(0, 0, mTaskViewRect.width(), getHeight(),
-                mCornerRadius, mCornerRadius, mDimLayerPaint);
-    }
-
-    @Override
     public void onClick(View v) {
         if (v == mIconView) {
             // In accessibility, a single click on the focused app info button will show it
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 36d7643..39d0604 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewThumbnail.java
@@ -93,6 +93,11 @@
      * to match the frame changes.
      */
     public void onTaskViewSizeChanged(int width, int height) {
+        // Return early if the bounds have not changed
+        if (mTaskViewRect.width() == width && mTaskViewRect.height() == height) {
+            return;
+        }
+
         mTaskViewRect.set(0, 0, width, height);
         updateThumbnailScale();
         invalidate();