Merge "Added haptic feedback when swipe/fling up from an app in fullscreen" into ub-launcher3-edmonton-polish
diff --git a/quickstep/AndroidManifest.xml b/quickstep/AndroidManifest.xml
index 778866d..cb74855 100644
--- a/quickstep/AndroidManifest.xml
+++ b/quickstep/AndroidManifest.xml
@@ -31,7 +31,7 @@
         android:hardwareAccelerated="true"
         android:icon="@drawable/ic_launcher_home"
         android:label="@string/derived_app_name"
-        android:theme="@style/LauncherTheme"
+        android:theme="@style/AppTheme"
         android:largeHeap="@bool/config_largeHeap"
         android:restoreAnyVersion="true"
         android:supportsRtl="true" >
diff --git a/quickstep/res/drawable/ic_split_screen.xml b/quickstep/res/drawable/ic_split_screen.xml
index 77bd333..110af91 100644
--- a/quickstep/res/drawable/ic_split_screen.xml
+++ b/quickstep/res/drawable/ic_split_screen.xml
@@ -13,33 +13,16 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
-        android:width="88.0dp"
-        android:height="88.0dp"
-        android:viewportWidth="88.0"
-        android:viewportHeight="88.0" >
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24"
+        android:viewportHeight="24">
 
     <path
-        android:pathData="M 32,11
-           C 32,11 68,11 68,11
-             76.74,11.06 76.98,12.76 77,21
-             77.01,25.97 78.50,38.23 73.85,40.98
-             71.80,42.19 68.35,42 66,42
-             66,42 22,42 22,42
-             18.82,41.99 14.87,42.38 12.60,39.69
-             10.71,37.44 11.01,33.77 11,31
-             10.99,25.54 9.53,16.08 13.31,12.02
-             18.07,10.21 26.66,11 32,11 Z
-           M 32,46
-           C 32,46 68,46 68,46
-             76.74,46.06 76.98,47.76 77,56
-             77.01,60.97 78.50,73.23 73.85,75.98
-             71.80,77.19 68.35,77 66,77
-             66,77 22,77 22,77
-             18.82,76.99 14.87,77.38 12.60,74.69
-             10.71,72.44 11.01,68.77 11,66
-             10.99,60.54 9.53,51.08 13.31,47.02
-             18.07,45.21 26.66,46 32,46 Z"
-        android:fillColor="@android:color/white" />
-</vector>
\ No newline at end of file
+        android:fillColor="@android:color/white"
+        android:pathData="M18,4v5H6V4H18 M18,2H6C4.9,2,4,2.9,4,4v5c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2V4C20,2.9,19.1,2,18,2L18,2z" />
+    <path
+        android:fillColor="@android:color/white"
+        android:pathData="M18,15v5H6v-5H18 M18,13H6c-1.1,0-2,0.9-2,2v5c0,1.1,0.9,2,2,2h12c1.1,0,2-0.9,2-2v-5C20,13.9,19.1,13,18,13L18,13z" />
+</vector>
diff --git a/quickstep/res/drawable/task_menu_bg.xml b/quickstep/res/drawable/task_menu_bg.xml
new file mode 100644
index 0000000..d5597a9
--- /dev/null
+++ b/quickstep/res/drawable/task_menu_bg.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 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.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:gravity="bottom">
+        <!-- Shadow -->
+        <shape>
+            <gradient android:angle="270"
+                android:endColor="@android:color/transparent"
+                android:startColor="#26000000" />
+            <size android:height="@dimen/task_card_menu_shadow_height" />
+        </shape>
+    </item>
+    <item android:bottom="@dimen/task_card_menu_shadow_height">
+        <!-- Background -->
+        <shape>
+            <corners
+                android:topLeftRadius="@dimen/task_corner_radius"
+                android:topRightRadius="@dimen/task_corner_radius"
+                android:bottomLeftRadius="0dp"
+                android:bottomRightRadius="0dp" />
+            <solid android:color="?attr/popupColorPrimary" />
+        </shape>
+    </item>
+</layer-list>
diff --git a/quickstep/res/layout/task_menu.xml b/quickstep/res/layout/task_menu.xml
index b846665..bf55ece 100644
--- a/quickstep/res/layout/task_menu.xml
+++ b/quickstep/res/layout/task_menu.xml
@@ -16,21 +16,31 @@
 -->
 <com.android.quickstep.views.TaskMenuView
     xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="@dimen/bg_popup_item_width"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:visibility="invisible"
-    android:elevation="@dimen/deep_shortcuts_elevation"
+    android:animateLayoutChanges="true"
+    android:background="@drawable/task_menu_bg"
+    android:paddingBottom="@dimen/task_card_menu_shadow_height"
     android:orientation="vertical"
-    android:background="?attr/popupColorPrimary"
-    android:divider="@drawable/all_apps_divider"
-    android:showDividers="middle"
-    android:animateLayoutChanges="true">
-        <TextView
-            android:id="@+id/task_icon_and_name"
-            android:layout_width="match_parent"
-            android:layout_height="112dp"
-            android:textSize="14sp"
-            android:paddingTop="18dp"
-            android:drawablePadding="8dp"
-            android:gravity="center_horizontal"/>
+    android:visibility="invisible">
+
+    <TextView
+        android:id="@+id/task_icon_and_name"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:drawablePadding="@dimen/deep_shortcut_drawable_padding"
+        android:gravity="center_horizontal"
+        android:layout_marginBottom="16dp"
+        android:textSize="12sp"/>
+
+    <LinearLayout
+        android:id="@+id/menu_option_layout"
+        style="@style/TaskMenu"
+        android:divider="@drawable/all_apps_divider"
+        android:showDividers="beginning"
+        android:paddingStart="@dimen/task_card_menu_horizontal_padding"
+        android:paddingEnd="@dimen/task_card_menu_horizontal_padding"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"/>
+
 </com.android.quickstep.views.TaskMenuView>
\ No newline at end of file
diff --git a/quickstep/res/layout/task_view_menu_option.xml b/quickstep/res/layout/task_view_menu_option.xml
new file mode 100644
index 0000000..102ae9b
--- /dev/null
+++ b/quickstep/res/layout/task_view_menu_option.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 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.
+-->
+
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    style="@style/TaskMenu.Option"
+    android:layout_height="wrap_content"
+    android:layout_gravity="center"
+    android:orientation="vertical"
+    android:paddingTop="@dimen/task_card_menu_option_vertical_padding"
+    android:paddingBottom="@dimen/task_card_menu_option_vertical_padding"
+    android:background="?android:attr/selectableItemBackground"
+    android:theme="@style/PopupItem" >
+
+    <View
+      android:id="@+id/icon"
+      android:layout_width="@dimen/system_shortcut_icon_size"
+      android:layout_height="@dimen/system_shortcut_icon_size"
+      android:layout_marginTop="@dimen/system_shortcut_header_icon_padding"
+      android:layout_marginBottom="@dimen/deep_shortcut_drawable_padding"
+      android:layout_gravity="center_horizontal"
+      android:backgroundTint="?android:attr/textColorTertiary"/>
+
+    <TextView
+        style="@style/BaseIcon"
+        android:id="@+id/text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:paddingBottom="@dimen/popup_padding_end"
+        android:textSize="12sp"
+        android:textColor="?android:attr/textColorPrimary"
+        android:fontFamily="sans-serif"
+        android:gravity="center_horizontal"
+        android:layout_gravity="center_horizontal"
+        android:focusable="false" />
+
+</LinearLayout>
diff --git a/quickstep/res/values-land/dimens.xml b/quickstep/res/values-land/dimens.xml
new file mode 100644
index 0000000..c03eaa2
--- /dev/null
+++ b/quickstep/res/values-land/dimens.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 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.
+-->
+<resources>
+    <dimen name="task_card_menu_horizontal_padding">24dp</dimen>
+</resources>
\ No newline at end of file
diff --git a/quickstep/res/values-land/styles.xml b/quickstep/res/values-land/styles.xml
new file mode 100644
index 0000000..0824b4f
--- /dev/null
+++ b/quickstep/res/values-land/styles.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 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.
+-->
+<resources>
+    <!-- Task Menu layout styles. -->
+    <style name="TaskMenu">
+        <item name="android:orientation">horizontal</item>
+    </style>
+
+    <!-- Task Menu Option layout styles. -->
+    <style name="TaskMenu.Option">
+        <item name="android:layout_width">0dp</item>
+        <item name="android:layout_weight">1</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index ed18bf5..ea7d21b 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -18,7 +18,6 @@
 
     <dimen name="task_thumbnail_top_margin">24dp</dimen>
     <dimen name="task_thumbnail_icon_size">48dp</dimen>
-    <dimen name="task_menu_background_radius">12dp</dimen>
     <dimen name="task_corner_radius">2dp</dimen>
     <dimen name="recents_page_spacing">10dp</dimen>
     <dimen name="quickscrub_adjacent_visible_width">20dp</dimen>
@@ -41,6 +40,9 @@
     <!-- Total space (start + end) between the task card and the edge of the screen
          in various configurations -->
     <dimen name="task_card_vert_space">40dp</dimen>
+    <dimen name="task_card_menu_option_vertical_padding">8dp</dimen>
+    <dimen name="task_card_menu_shadow_height">3dp</dimen>
+    <dimen name="task_card_menu_horizontal_padding">0dp</dimen>
     <dimen name="portrait_task_card_horz_space">136dp</dimen>
     <dimen name="landscape_task_card_horz_space">200dp</dimen>
     <dimen name="multi_window_task_card_horz_space">100dp</dimen>
@@ -52,4 +54,6 @@
     <dimen name="clear_all_container_width">168dp</dimen>
 
     <dimen name="shelf_surface_radius">16dp</dimen>
+    <!-- same as vertical_drag_handle_size -->
+    <dimen name="shelf_surface_offset">24dp</dimen>
 </resources>
diff --git a/quickstep/res/values/styles.xml b/quickstep/res/values/styles.xml
new file mode 100644
index 0000000..bb364ff
--- /dev/null
+++ b/quickstep/res/values/styles.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2018 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.
+-->
+<resources>
+    <!-- Task Menu layout styles. -->
+    <style name="TaskMenu">
+        <item name="android:orientation">vertical</item>
+    </style>
+
+    <!-- Task Menu Option layout styles. -->
+    <style name="TaskMenu.Option">
+        <item name="android:layout_width">match_parent</item>
+        <item name="android:layout_height">wrap_content</item>
+    </style>
+</resources>
\ No newline at end of file
diff --git a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
index 4c90cbe..72d6260 100644
--- a/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
+++ b/quickstep/src/com/android/launcher3/LauncherAppTransitionManagerImpl.java
@@ -618,7 +618,7 @@
                         targetCrop = crop;
                         alpha = mAlpha.value;
                     } else {
-                        matrix.reset();
+                        matrix.setTranslate(target.position.x, target.position.y);
                         alpha = 1f;
                         targetCrop = target.sourceContainerBounds;
                     }
@@ -736,7 +736,7 @@
                         matrix.postTranslate(target.position.x, target.position.y);
                         alpha = mAlpha.value;
                     } else {
-                        matrix.reset();
+                        matrix.setTranslate(target.position.x, target.position.y);
                         alpha = 1f;
                     }
                     params[i] = new SurfaceParams(target.leash, alpha, matrix,
diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
index c780b62..d7e527c 100644
--- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
+++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
@@ -15,11 +15,11 @@
  */
 package com.android.quickstep.views;
 
-import static android.support.v4.graphics.ColorUtils.compositeColors;
 import static android.support.v4.graphics.ColorUtils.setAlphaComponent;
 
 import static com.android.launcher3.LauncherState.OVERVIEW;
-import static com.android.launcher3.anim.Interpolators.ACCEL_2;
+import static com.android.launcher3.anim.Interpolators.ACCEL;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
 
 import android.content.Context;
 import android.graphics.Canvas;
@@ -32,7 +32,7 @@
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
-import com.android.launcher3.uioverrides.OverviewState;
+import com.android.launcher3.Utilities;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.views.ScrimView;
 
@@ -45,22 +45,30 @@
  */
 public class ShelfScrimView extends ScrimView {
 
+    // If the progress is more than this, shelf follows the finger, otherwise it moves faster to
+    // cover the whole screen
+    private static final float SCRIM_CATCHUP_THRESHOLD = 0.2f;
+
     // In transposed layout, we simply draw a flat color.
     private boolean mDrawingFlatColor;
 
     // For shelf mode
     private final int mEndAlpha;
-    private final int mThresholdAlpha;
     private final float mRadius;
     private final float mMaxScrimAlpha;
     private final Paint mPaint;
 
-    // Max vertical progress after which the scrim stops moving.
-    private float mMoveThreshold;
-    // Minimum visible size of the scrim.
-    private int mMinSize;
+    // Mid point where the alpha changes
+    private int mMidAlpha;
+    private float mMidProgress;
 
-    private float mScrimMoveFactor = 0;
+    private float mShiftRange;
+
+    private final float mShelfOffset;
+    private float mTopOffset;
+    private float mShelfTop;
+    private float mShelfTopAtThreshold;
+
     private int mShelfColor;
     private int mRemainingScreenColor;
 
@@ -73,10 +81,10 @@
         mMaxScrimAlpha = OVERVIEW.getWorkspaceScrimAlpha(mLauncher);
 
         mEndAlpha = Color.alpha(mEndScrim);
-        mThresholdAlpha = Themes.getAttrInteger(context, R.attr.allAppsInterimScrimAlpha);
         mRadius = mLauncher.getResources().getDimension(R.dimen.shelf_surface_radius);
         mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
 
+        mShelfOffset = context.getResources().getDimension(R.dimen.shelf_surface_offset);
         // Just assume the easiest UI for now, until we have the proper layout information.
         mDrawingFlatColor = true;
     }
@@ -93,10 +101,15 @@
         mDrawingFlatColor = dp.isVerticalBarLayout();
 
         if (!mDrawingFlatColor) {
-            float swipeLength = OverviewState.getDefaultSwipeHeight(mLauncher);
-            mMoveThreshold = 1 - swipeLength / mLauncher.getAllAppsController().getShiftRange();
-            mMinSize = dp.hotseatBarSizePx + dp.getInsets().bottom;
             mRemainingScreenPathValid = false;
+            mShiftRange = mLauncher.getAllAppsController().getShiftRange();
+
+            mMidProgress = OVERVIEW.getVerticalProgress(mLauncher);
+            mMidAlpha = mMidProgress >= 1 ? 0
+                    : Themes.getAttrInteger(getContext(), R.attr.allAppsInterimScrimAlpha);
+
+            mTopOffset = dp.getInsets().top - mShelfOffset;
+            mShelfTopAtThreshold = mShiftRange * SCRIM_CATCHUP_THRESHOLD + mTopOffset;
             updateColors();
         }
         updateDragHandleAlpha();
@@ -107,82 +120,79 @@
     public void updateColors() {
         super.updateColors();
         if (mDrawingFlatColor) {
+            mDragHandleOffset = 0;
             return;
         }
 
-        if (mProgress >= mMoveThreshold) {
-            mScrimMoveFactor = 1;
-
-            if (mProgress >= 1) {
-                mShelfColor = 0;
-            } else {
-                int alpha = Math.round(mThresholdAlpha * ACCEL_2.getInterpolation(
-                        (1 - mProgress) / (1 - mMoveThreshold)));
-                mShelfColor = setAlphaComponent(mEndScrim, alpha);
-            }
-
-            mRemainingScreenColor = 0;
-        } else if (mProgress <= 0) {
-            mScrimMoveFactor = 0;
-            mShelfColor = mCurrentFlatColor;
-            mRemainingScreenColor = 0;
-
+        mDragHandleOffset = mShelfOffset - mDragHandleSize;
+        if (mProgress >= SCRIM_CATCHUP_THRESHOLD) {
+            mShelfTop = mShiftRange * mProgress + mTopOffset;
         } else {
-            mScrimMoveFactor = mProgress / mMoveThreshold;
-            mRemainingScreenColor = setAlphaComponent(mScrimColor,
-                    Math.round((1 - mScrimMoveFactor) * mMaxScrimAlpha * 255));
+            mShelfTop = Utilities.mapRange(mProgress / SCRIM_CATCHUP_THRESHOLD, -mRadius,
+                    mShelfTopAtThreshold);
+        }
 
-            // Merge the remainingScreenColor and shelfColor in one to avoid overdraw.
-            int alpha = mEndAlpha - Math.round((mEndAlpha - mThresholdAlpha) * mScrimMoveFactor);
-            mShelfColor = compositeColors(setAlphaComponent(mEndScrim, alpha),
-                    mRemainingScreenColor);
+        if (mProgress >= 1) {
+            mRemainingScreenColor = 0;
+            mShelfColor = 0;
+        } else if (mProgress >= mMidProgress) {
+            mRemainingScreenColor = 0;
+
+            int alpha = Math.round(Utilities.mapToRange(
+                    mProgress, mMidProgress, 1, mMidAlpha, 0, ACCEL));
+            mShelfColor = setAlphaComponent(mEndScrim, alpha);
+        } else {
+            mDragHandleOffset += mShiftRange * (mMidProgress - mProgress);
+
+            int alpha = Math.round(
+                    Utilities.mapToRange(mProgress, (float) 0, mMidProgress, (float) mEndAlpha,
+                            (float) mMidAlpha, LINEAR));
+            mShelfColor = setAlphaComponent(mEndScrim, alpha);
+
+            int remainingScrimAlpha = Math.round(
+                    Utilities.mapToRange(mProgress, (float) 0, mMidProgress, mMaxScrimAlpha,
+                            (float) 0, LINEAR));
+            mRemainingScreenColor = setAlphaComponent(mScrimColor, remainingScrimAlpha);
         }
     }
 
     @Override
     protected void onDraw(Canvas canvas) {
-        float translate = drawBackground(canvas);
-
-        if (mDragHandle != null) {
-            canvas.translate(0, -translate);
-            mDragHandle.draw(canvas);
-            canvas.translate(0, translate);
-        }
+        drawBackground(canvas);
+        drawDragHandle(canvas);
     }
 
-    private float drawBackground(Canvas canvas) {
+    private void drawBackground(Canvas canvas) {
         if (mDrawingFlatColor) {
             if (mCurrentFlatColor != 0) {
                 canvas.drawColor(mCurrentFlatColor);
             }
-            return 0;
+            return;
         }
 
-        if (mShelfColor == 0) {
-            return 0;
-        } else if (mScrimMoveFactor <= 0) {
+        if (Color.alpha(mShelfColor) == 0) {
+            return;
+        } else if (mProgress <= 0) {
             canvas.drawColor(mShelfColor);
-            return getHeight();
+            return;
         }
 
-        float minTop = getHeight() - mMinSize;
-        float top = minTop * mScrimMoveFactor - mDragHandleSize;
-
+        int height = getHeight();
+        int width = getWidth();
         // Draw the scrim over the remaining screen if needed.
         if (mRemainingScreenColor != 0) {
             if (!mRemainingScreenPathValid) {
                 mTempPath.reset();
                 // Using a arbitrary '+10' in the bottom to avoid any left-overs at the
                 // corners due to rounding issues.
-                mTempPath.addRoundRect(0, minTop, getWidth(), getHeight() + mRadius + 10,
+                mTempPath.addRoundRect(0, height - mRadius, width, height + mRadius + 10,
                         mRadius, mRadius, Direction.CW);
-
                 mRemainingScreenPath.reset();
-                mRemainingScreenPath.addRect(0, 0, getWidth(), getHeight(), Direction.CW);
+                mRemainingScreenPath.addRect(0, 0, width, height, Direction.CW);
                 mRemainingScreenPath.op(mTempPath, Op.DIFFERENCE);
             }
 
-            float offset = minTop - top;
+            float offset = height - mRadius - mShelfTop;
             canvas.translate(0, -offset);
             mPaint.setColor(mRemainingScreenColor);
             canvas.drawPath(mRemainingScreenPath, mPaint);
@@ -190,8 +200,6 @@
         }
 
         mPaint.setColor(mShelfColor);
-        canvas.drawRoundRect(0, top, getWidth(), getHeight() + mRadius,
-                mRadius, mRadius, mPaint);
-        return minTop - mDragHandleSize - top;
+        canvas.drawRoundRect(0, mShelfTop, width, height + mRadius, mRadius, mRadius, mPaint);
     }
 }
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index dd90c88..39f5323 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -16,19 +16,19 @@
 
 package com.android.quickstep.views;
 
+import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
+
 import android.animation.Animator;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.content.Context;
-import android.graphics.Outline;
-import android.graphics.Point;
+import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
-import android.view.View;
-import android.view.ViewOutlineProvider;
-import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.ViewGroup;
+import android.widget.LinearLayout;
 import android.widget.TextView;
 
 import com.android.launcher3.AbstractFloatingView;
@@ -37,8 +37,8 @@
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
-import com.android.launcher3.shortcuts.DeepShortcutView;
 import com.android.launcher3.views.BaseDragLayer;
 import com.android.quickstep.TaskSystemShortcut;
 import com.android.quickstep.TaskUtils;
@@ -58,12 +58,14 @@
             new TaskSystemShortcut.Install(),
     };
 
-    private static final long OPEN_CLOSE_DURATION = 220;
+    private static final int REVEAL_OPEN_DURATION = 150;
+    private static final int REVEAL_CLOSE_DURATION = 100;
 
     private BaseDraggingActivity mActivity;
     private TextView mTaskIconAndName;
     private AnimatorSet mOpenCloseAnimator;
     private TaskView mTaskView;
+    private LinearLayout mOptionLayout;
 
     public TaskMenuView(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
@@ -73,20 +75,13 @@
         super(context, attrs, defStyleAttr);
 
         mActivity = BaseDraggingActivity.fromContext(context);
-        setClipToOutline(true);
-        setOutlineProvider(new ViewOutlineProvider() {
-            @Override
-            public void getOutline(View view, Outline outline) {
-                float r = getResources().getDimensionPixelSize(R.dimen.task_menu_background_radius);
-                outline.setRoundRect(0, 0, view.getWidth(), view.getHeight(), r);
-            }
-        });
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
         mTaskIconAndName = findViewById(R.id.task_icon_and_name);
+        mOptionLayout = findViewById(R.id.menu_option_layout);
     }
 
     @Override
@@ -148,6 +143,12 @@
         mTaskIconAndName.setText(TaskUtils.getTitle(getContext(), taskView.getTask()));
         mTaskIconAndName.setOnClickListener(v -> close(true));
 
+        // Move the icon and text up half an icon size to lay over the TaskView
+        LinearLayout.LayoutParams params =
+                (LinearLayout.LayoutParams) mTaskIconAndName.getLayoutParams();
+        params.topMargin = (int) -getResources().getDimension(R.dimen.task_thumbnail_top_margin);
+        mTaskIconAndName.setLayoutParams(params);
+
         for (TaskSystemShortcut menuOption : MENU_OPTIONS) {
             OnClickListener onClickListener = menuOption.getOnClickListener(mActivity, taskView);
             if (onClickListener != null) {
@@ -157,21 +158,24 @@
     }
 
     private void addMenuOption(TaskSystemShortcut menuOption, OnClickListener onClickListener) {
-        DeepShortcutView menuOptionView = (DeepShortcutView) mActivity.getLayoutInflater().inflate(
-                R.layout.system_shortcut, this, false);
-        menuOptionView.getIconView().setBackgroundResource(menuOption.iconResId);
-        menuOptionView.getBubbleText().setText(menuOption.labelResId);
+        ViewGroup menuOptionView = (ViewGroup) mActivity.getLayoutInflater().inflate(
+                R.layout.task_view_menu_option, this, false);
+        menuOptionView.findViewById(R.id.icon).setBackgroundResource(menuOption.iconResId);
+        ((TextView) menuOptionView.findViewById(R.id.text)).setText(menuOption.labelResId);
         menuOptionView.setOnClickListener(onClickListener);
-        addView(menuOptionView);
+        mOptionLayout.addView(menuOptionView);
     }
 
     private void orientAroundTaskView(TaskView taskView) {
         measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
         mActivity.getDragLayer().getDescendantRectRelativeToSelf(taskView, sTempRect);
         Rect insets = mActivity.getDragLayer().getInsets();
-        int x = sTempRect.left + (sTempRect.width() - getMeasuredWidth()) / 2 - insets.left;
-        setX(Utilities.isRtl(getResources()) ? -x : x);
-        setY(sTempRect.top - mTaskIconAndName.getPaddingTop() - insets.top);
+        BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) getLayoutParams();
+        params.width = sTempRect.width();
+        setLayoutParams(params);
+        setX(Utilities.isRtl(getResources()) ? -sTempRect.left : sTempRect.left);
+        setY(sTempRect.top + getResources().getDimension(R.dimen.task_thumbnail_top_margin)
+                - insets.top);
     }
 
     private void animateOpen() {
@@ -188,8 +192,13 @@
             return;
         }
         mOpenCloseAnimator = LauncherAnimUtils.createAnimatorSet();
-        mOpenCloseAnimator.play(createOpenCloseOutlineProvider()
-                .createRevealAnimator(this, closing));
+
+        final Animator revealAnimator = createOpenCloseOutlineProvider()
+                .createRevealAnimator(this, closing);
+        revealAnimator.setInterpolator(Interpolators.DEACCEL);
+        mOpenCloseAnimator.play(revealAnimator);
+        mOpenCloseAnimator.play(ObjectAnimator.ofFloat(mTaskView.getThumbnail(), DIM_ALPHA,
+                closing ? 0 : TaskView.MAX_PAGE_SCRIM_ALPHA));
         mOpenCloseAnimator.addListener(new AnimationSuccessListener() {
             @Override
             public void onAnimationStart(Animator animation) {
@@ -204,8 +213,7 @@
             }
         });
         mOpenCloseAnimator.play(ObjectAnimator.ofFloat(this, ALPHA, closing ? 0 : 1));
-        mOpenCloseAnimator.setDuration(OPEN_CLOSE_DURATION);
-        mOpenCloseAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
+        mOpenCloseAnimator.setDuration(closing ? REVEAL_CLOSE_DURATION: REVEAL_OPEN_DURATION);
         mOpenCloseAnimator.start();
     }
 
@@ -215,18 +223,9 @@
     }
 
     private RoundedRectRevealOutlineProvider createOpenCloseOutlineProvider() {
-        int iconSize = getResources().getDimensionPixelSize(R.dimen.task_thumbnail_icon_size);
-        float fromRadius = iconSize / 2;
-        float toRadius = getResources().getDimensionPixelSize(
-                R.dimen.task_menu_background_radius);
-        Point iconCenter = new Point(getWidth() / 2, mTaskIconAndName.getPaddingTop() + iconSize / 2);
-        Rect fromRect = new Rect(iconCenter.x, iconCenter.y, iconCenter.x, iconCenter.y);
+        float radius = getResources().getDimension(R.dimen.task_corner_radius);
+        Rect fromRect = new Rect(0, 0, getWidth(), 0);
         Rect toRect = new Rect(0, 0, getWidth(), getHeight());
-        return new RoundedRectRevealOutlineProvider(fromRadius, toRadius, fromRect, toRect) {
-            @Override
-            public boolean shouldRemoveElevationDuringAnimation() {
-                return true;
-            }
-        };
+        return new RoundedRectRevealOutlineProvider(radius, radius, fromRect, toRect);
     }
 }
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index d9dfd18..07f22aa 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -29,7 +29,6 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.graphics.Shader;
-import android.support.v4.graphics.ColorUtils;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
 import android.util.Property;
@@ -68,6 +67,19 @@
                 }
             };
 
+    public static final Property<TaskThumbnailView, Float> DIM_ALPHA =
+            new FloatProperty<TaskThumbnailView>("dimAlpha") {
+                @Override
+                public void setValue(TaskThumbnailView thumbnail, float dimAlpha) {
+                    thumbnail.setDimAlpha(dimAlpha);
+                }
+
+                @Override
+                public Float get(TaskThumbnailView thumbnailView) {
+                    return thumbnailView.mDimAlpha;
+                }
+            };
+
     private final float mCornerRadius;
 
     private final BaseActivity mActivity;
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index a7690e1..468efd8 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -71,7 +71,7 @@
      * The alpha of a black scrim on a page in the carousel as it leaves the screen.
      * In the resting position of the carousel, the adjacent pages have about half this scrim.
      */
-    private static final float MAX_PAGE_SCRIM_ALPHA = 0.4f;
+    public static final float MAX_PAGE_SCRIM_ALPHA = 0.4f;
 
     /**
      * How much to scale down pages near the edge of the screen.
diff --git a/res/drawable/ic_info_no_shadow.xml b/res/drawable/ic_info_no_shadow.xml
index b5512c3..d816f12 100644
--- a/res/drawable/ic_info_no_shadow.xml
+++ b/res/drawable/ic_info_no_shadow.xml
@@ -16,12 +16,17 @@
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
         android:width="24dp"
         android:height="24dp"
-        android:viewportWidth="24.0"
-        android:viewportHeight="24.0"
-        android:tint="?android:attr/textColorPrimary" >
+        android:viewportWidth="24"
+        android:viewportHeight="24"
+        android:tint="?android:attr/textColorPrimary">
+
     <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M12,17L12,17c0.55,0,1-0.45,1-1v-4c0-0.55-0.45-1-1-1l0,0c-0.55,0-1,0.45-1,1v4C11,16.55,11.45,17,12,17z M12,2C6.48,
-        2,2,6.48,2,12s4.48,10,10,10s10-4.48,10-10S17.52,2,12,2z M12,20c-4.41,0-8-3.59-8-8s3.59-8,8-8s8,3.59,8,8S16.41,20,12,20zM12,
-        9.1L12,9.1c0.61,0,1.1-0.49,1.1-1.1l0,0c0-0.61-0.49-1.1-1.1-1.1l0,0c-0.61,0-1.1,0.49-1.1,1.1l0,0C10.9,8.61,11.39,9.1,12,9.1z"/>
+        android:fillColor="#FFFFFF"
+        android:pathData="M 11 7 H 13 V 9 H 11 V 7 Z" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M 11 11 H 13 V 17 H 11 V 11 Z" />
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M12,2C6.48,2,2,6.48,2,12c0,5.52,4.48,10,10,10s10-4.48,10-10C22,6.48,17.52,2,12,2z M12,20c-4.41,0-8-3.59-8-8 c0-4.41,3.59-8,8-8s8,3.59,8,8C20,16.41,16.41,20,12,20z" />
 </vector>
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 5355c5e..7fe8d35 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -48,6 +48,7 @@
 import android.util.Pair;
 import android.util.TypedValue;
 import android.view.View;
+import android.view.animation.Interpolator;
 
 import com.android.launcher3.config.FeatureFlags;
 
@@ -281,13 +282,14 @@
      * @param toMax The upper bound of the range that t is being mapped to.
      * @return The mapped value of t.
      */
-    public static float mapToRange(float t, float fromMin, float fromMax, float toMin, float toMax) {
+    public static float mapToRange(float t, float fromMin, float fromMax, float toMin, float toMax,
+            Interpolator interpolator) {
         if (fromMin == fromMax || toMin == toMax) {
             Log.e(TAG, "mapToRange: range has 0 length");
             return toMin;
         }
         float progress = Math.abs(t - fromMin) / Math.abs(fromMax - fromMin);
-        return mapRange(progress, toMin, toMax);
+        return mapRange(interpolator.getInterpolation(progress), toMin, toMax);
     }
 
     public static float mapRange(float value, float min, float max) {
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index d17572e..a4cba4f 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -158,7 +158,6 @@
      */
     public static Interpolator mapToProgress(Interpolator interpolator, float lowerBound,
             float upperBound) {
-        return t -> Utilities.mapToRange(interpolator.getInterpolation(t), 0, 1,
-                lowerBound, upperBound);
+        return t -> Utilities.mapRange(interpolator.getInterpolation(t), lowerBound, upperBound);
     }
 }
\ No newline at end of file
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index 6e3ef07..7066980 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -109,6 +109,7 @@
     protected int mEndFlatColorAlpha;
 
     protected final int mDragHandleSize;
+    protected float mDragHandleOffset;
     private final Rect mDragHandleBounds;
     private final RectF mHitRect = new RectF();
 
@@ -223,8 +224,14 @@
         if (mCurrentFlatColor != 0) {
             canvas.drawColor(mCurrentFlatColor);
         }
+        drawDragHandle(canvas);
+    }
+
+    protected void drawDragHandle(Canvas canvas) {
         if (mDragHandle != null) {
+            canvas.translate(0, -mDragHandleOffset);
             mDragHandle.draw(canvas);
+            canvas.translate(0, mDragHandleOffset);
         }
     }
 
@@ -237,20 +244,23 @@
 
             final Drawable drawable = mDragHandle;
             mDragHandle = null;
-            drawable.setBounds(mDragHandleBounds);
 
-            Rect topBounds = new Rect(mDragHandleBounds);
-            topBounds.offset(0, -mDragHandleBounds.height() / 2);
+            Rect bounds = new Rect(mDragHandleBounds);
+            bounds.offset(0, -(int) mDragHandleOffset);
+            drawable.setBounds(bounds);
 
-            Rect invalidateRegion = new Rect(mDragHandleBounds);
+            Rect topBounds = new Rect(bounds);
+            topBounds.offset(0, -bounds.height() / 2);
+
+            Rect invalidateRegion = new Rect(bounds);
             invalidateRegion.top = topBounds.top;
 
             Keyframe frameTop = Keyframe.ofObject(0.6f, topBounds);
             frameTop.setInterpolator(DEACCEL);
-            Keyframe frameBot = Keyframe.ofObject(1, mDragHandleBounds);
+            Keyframe frameBot = Keyframe.ofObject(1, bounds);
             frameBot.setInterpolator(ACCEL);
             PropertyValuesHolder holder = PropertyValuesHolder .ofKeyframe("bounds",
-                    Keyframe.ofObject(0, mDragHandleBounds), frameTop, frameBot);
+                    Keyframe.ofObject(0, bounds), frameTop, frameBot);
             holder.setEvaluator(new RectEvaluator());
 
             ObjectAnimator anim = ObjectAnimator.ofPropertyValuesHolder(drawable, holder);