Update vertical drag handle (all apps arrow)

- Change drawable to match specs, using ShadowDrawable to
  add shadow when necessary based on workspace theme.
- New drawable is 18dp by 6dp; add support for different
  width vs height, and decouple from workspace page
  indicator (which is still 24dp tall).

Bug: 151768994
Change-Id: Icfd0eac197ebc4d1f5bb799f8538c4bd99d800cd
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 8d42c4a..dcc85d5 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -66,9 +66,6 @@
        docked_stack_divider_thickness - 2 * docked_stack_divider_insets -->
     <dimen name="multi_window_task_divider_size">10dp</dimen>
 
-    <!-- same as vertical_drag_handle_size -->
-    <dimen name="shelf_surface_offset">24dp</dimen>
-
     <!-- Assistant Gestures -->
     <!-- Distance from the vertical edges of the screen in which assist gestures are recognized -->
     <dimen name="gestures_assistant_width">48dp</dimen>
diff --git a/quickstep/src/com/android/quickstep/util/LayoutUtils.java b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
index ba99016..1f1a999 100644
--- a/quickstep/src/com/android/quickstep/util/LayoutUtils.java
+++ b/quickstep/src/com/android/quickstep/util/LayoutUtils.java
@@ -33,9 +33,6 @@
 
 import java.lang.annotation.Retention;
 
-import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
-import static java.lang.annotation.RetentionPolicy.SOURCE;
-
 public class LayoutUtils {
 
     private static final int MULTI_WINDOW_STRATEGY_HALF_SCREEN = 1;
@@ -68,7 +65,7 @@
                 // UI when shown.
                 extraSpace = 0;
             } else {
-                extraSpace = getDefaultSwipeHeight(context, dp) + dp.verticalDragHandleSizePx
+                extraSpace = getDefaultSwipeHeight(context, dp) + dp.workspacePageIndicatorHeight
                         + res.getDimensionPixelSize(
                                 R.dimen.dynamic_grid_hotseat_extra_vertical_size)
                         + res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
diff --git a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
index 14c458e..c2ccd90 100644
--- a/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
+++ b/quickstep/src/com/android/quickstep/views/ShelfScrimView.java
@@ -88,7 +88,6 @@
 
     private float mShiftRange;
 
-    private final float mShelfOffset;
     private float mTopOffset;
     private float mShelfTop;
     private float mShelfTopAtThreshold;
@@ -110,7 +109,6 @@
         mRadius = BOTTOM_CORNER_RADIUS_RATIO * Themes.getDialogCornerRadius(context);
         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;
     }
@@ -179,7 +177,7 @@
                         Math.min(hotseatSize, LayoutUtils.getDefaultSwipeHeight(context, dp));
                 mDragHandleProgress =  1 - (dragHandleTop / mShiftRange);
             }
-            mTopOffset = dp.getInsets().top - mShelfOffset;
+            mTopOffset = dp.getInsets().top - mDragHandleSize.y;
             mShelfTopAtThreshold = mShiftRange * SCRIM_CATCHUP_THRESHOLD + mTopOffset;
         }
         updateColors();
@@ -190,12 +188,15 @@
     @Override
     public void updateColors() {
         super.updateColors();
+        mDragHandleOffset = 0;
         if (mDrawingFlatColor) {
-            mDragHandleOffset = 0;
             return;
         }
 
-        mDragHandleOffset = mShelfOffset - mDragHandleSize;
+        if (mProgress < mDragHandleProgress) {
+            mDragHandleOffset = mShiftRange * (mDragHandleProgress - mProgress);
+        }
+
         if (mProgress >= SCRIM_CATCHUP_THRESHOLD) {
             mShelfTop = mShiftRange * mProgress + mTopOffset;
         } else {
@@ -231,10 +232,6 @@
                             (float) 0, LINEAR));
             mRemainingScreenColor = setColorAlphaBound(mScrimColor, remainingScrimAlpha);
         }
-
-        if (mProgress < mDragHandleProgress) {
-            mDragHandleOffset += mShiftRange * (mDragHandleProgress - mProgress);
-        }
     }
 
     @Override
@@ -290,4 +287,9 @@
         mPaint.setColor(mShelfColor);
         canvas.drawRoundRect(0, mShelfTop, width, height + mRadius, mRadius, mRadius, mPaint);
     }
+
+    @Override
+    public float getVisualTop() {
+        return mShelfTop;
+    }
 }
diff --git a/res/drawable-v24/drag_handle_indicator_shadow.xml b/res/drawable-v24/drag_handle_indicator_shadow.xml
new file mode 100644
index 0000000..774bc38
--- /dev/null
+++ b/res/drawable-v24/drag_handle_indicator_shadow.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+<com.android.launcher3.graphics.ShadowDrawable
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:src="@drawable/drag_handle_indicator_no_shadow"
+    android:elevation="@dimen/vertical_drag_handle_elevation" />
diff --git a/res/drawable/drag_handle_indicator.xml b/res/drawable/drag_handle_indicator.xml
deleted file mode 100644
index b01b84a..0000000
--- a/res/drawable/drag_handle_indicator.xml
+++ /dev/null
@@ -1,40 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2017 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.
--->
-
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
-    android:width="@dimen/vertical_drag_handle_size"
-    android:height="@dimen/vertical_drag_handle_size"
-    android:viewportWidth="36.0"
-    android:viewportHeight="36.0" >
-
-    <group
-        android:translateX="11.5"
-        android:translateY="11.5">
-        <path
-            android:pathData="M2 8.5L6.5 4L11 8.5"
-            android:strokeColor="?attr/workspaceAmbientShadowColor"
-            android:strokeWidth="3.6"
-            android:strokeLineCap="round"
-            android:strokeLineJoin="round" />
-
-        <path
-            android:pathData="M2 8.5L6.5 4L11 8.5"
-            android:strokeColor="?attr/workspaceTextColor"
-            android:strokeWidth="1.8"
-            android:strokeLineCap="round"
-            android:strokeLineJoin="round" />
-        </group>
-</vector>
diff --git a/res/drawable/drag_handle_indicator_no_shadow.xml b/res/drawable/drag_handle_indicator_no_shadow.xml
new file mode 100644
index 0000000..341e60c
--- /dev/null
+++ b/res/drawable/drag_handle_indicator_no_shadow.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 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.
+-->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="@dimen/vertical_drag_handle_width"
+    android:height="@dimen/vertical_drag_handle_height"
+    android:viewportWidth="18.0"
+    android:viewportHeight="6.0"
+    android:tint="?attr/workspaceTextColor" >
+
+    <path
+        android:pathData="M17,6c-0.15,0-0.3-0.03-0.45-0.11L9,2.12L1.45,5.89c-0.5,0.25-1.09,
+        0.05-1.34-0.45S0.06,4.35,0.55,4.11l8-4c0.28-0.14,0.61-0.14,0.89,0l8,4c0.49,0.25,0.69,
+        0.85,0.45,1.34C17.72,5.8,17.37,6,17,6z"
+        android:fillColor="@android:color/white" />
+</vector>
diff --git a/res/layout/launcher.xml b/res/layout/launcher.xml
index ab6c960..de13277 100644
--- a/res/layout/launcher.xml
+++ b/res/layout/launcher.xml
@@ -57,7 +57,7 @@
         <com.android.launcher3.pageindicators.WorkspacePageIndicator
             android:id="@+id/page_indicator"
             android:layout_width="match_parent"
-            android:layout_height="@dimen/vertical_drag_handle_size"
+            android:layout_height="@dimen/workspace_page_indicator_height"
             android:layout_gravity="bottom|center_horizontal"
             android:theme="@style/HomeScreenElementTheme" />
 
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 271511e..0b589a2 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -20,7 +20,6 @@
 
     <!-- Dynamic Grid -->
     <dimen name="dynamic_grid_edge_margin">8dp</dimen>
-    <dimen name="dynamic_grid_page_indicator_line_height">1dp</dimen>
     <dimen name="dynamic_grid_icon_drawable_padding">8dp</dimen>
     <!-- Minimum space between workspace and hotseat in spring loaded mode -->
     <dimen name="dynamic_grid_min_spring_loaded_space">8dp</dimen>
@@ -36,10 +35,18 @@
     <dimen name="dynamic_grid_hotseat_extra_vertical_size">34dp</dimen>
     <dimen name="dynamic_grid_hotseat_side_padding">0dp</dimen>
 
+    <!-- Workspace page indicator -->
+    <dimen name="workspace_page_indicator_height">24dp</dimen>
+    <dimen name="workspace_page_indicator_line_height">1dp</dimen>
+    <dimen name="workspace_page_indicator_overlap_workspace">0dp</dimen>
+
     <!-- Hotseat/all-apps scrim -->
     <dimen name="all_apps_scrim_blur">4dp</dimen>
-    <dimen name="vertical_drag_handle_size">24dp</dimen>
-    <dimen name="vertical_drag_handle_overlap_workspace">0dp</dimen>
+    <dimen name="vertical_drag_handle_width">18dp</dimen>
+    <dimen name="vertical_drag_handle_height">6dp</dimen>
+    <dimen name="vertical_drag_handle_elevation">1dp</dimen>
+    <dimen name="vertical_drag_handle_touch_size">48dp</dimen>
+    <dimen name="vertical_drag_handle_padding_in_vertical_bar_layout">16dp</dimen>
 
 <!-- Drop target bar -->
     <dimen name="dynamic_grid_drop_target_size">48dp</dimen>
diff --git a/res/values/drawables.xml b/res/values/drawables.xml
index 9c57ec1..7d63142 100644
--- a/res/values/drawables.xml
+++ b/res/values/drawables.xml
@@ -18,4 +18,5 @@
     <drawable name="ic_remove_shadow">@drawable/ic_remove_no_shadow</drawable>
     <drawable name="ic_uninstall_shadow">@drawable/ic_uninstall_no_shadow</drawable>
     <drawable name="ic_block_shadow">@drawable/ic_block_no_shadow</drawable>
+    <drawable name="all_apps_arrow_shadow">@drawable/drag_handle_indicator_no_shadow</drawable>
 </resources>
\ No newline at end of file
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index c049069..4e1e586 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -76,9 +76,9 @@
     public float workspaceSpringLoadShrinkFactor;
     public final int workspaceSpringLoadedBottomSpace;
 
-    // Drag handle
-    public final int verticalDragHandleSizePx;
-    private final int verticalDragHandleOverlapWorkspace;
+    // Workspace page indicator
+    public final int workspacePageIndicatorHeight;
+    private final int mWorkspacePageIndicatorOverlapWorkspace;
 
     // Workspace icons
     public int iconSizePx;
@@ -190,10 +190,10 @@
             cellLayoutBottomPaddingPx = 0;
         }
 
-        verticalDragHandleSizePx = res.getDimensionPixelSize(
-                R.dimen.vertical_drag_handle_size);
-        verticalDragHandleOverlapWorkspace =
-                res.getDimensionPixelSize(R.dimen.vertical_drag_handle_overlap_workspace);
+        workspacePageIndicatorHeight = res.getDimensionPixelSize(
+                R.dimen.workspace_page_indicator_height);
+        mWorkspacePageIndicatorOverlapWorkspace =
+                res.getDimensionPixelSize(R.dimen.workspace_page_indicator_overlap_workspace);
 
         iconDrawablePaddingOriginalPx =
                 res.getDimensionPixelSize(R.dimen.dynamic_grid_icon_drawable_padding);
@@ -211,7 +211,7 @@
         hotseatBarSidePaddingEndPx =
                 res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_side_padding);
         // Add a bit of space between nav bar and hotseat in vertical bar layout.
-        hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? verticalDragHandleSizePx : 0;
+        hotseatBarSidePaddingStartPx = isVerticalBarLayout() ? workspacePageIndicatorHeight : 0;
         hotseatBarSizePx = ResourceUtils.pxFromDp(inv.iconSize, dm) + (isVerticalBarLayout()
                 ? (hotseatBarSidePaddingStartPx + hotseatBarSidePaddingEndPx)
                 : (res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_extra_vertical_size)
@@ -227,7 +227,7 @@
             // in portrait mode closer together by adding more height to the hotseat.
             // Note: This calculation was created after noticing a pattern in the design spec.
             int extraSpace = getCellSize().y - iconSizePx - iconDrawablePaddingPx * 2
-                    - verticalDragHandleSizePx;
+                    - workspacePageIndicatorHeight;
             hotseatBarSizePx += extraSpace;
             hotseatBarBottomPaddingPx += extraSpace;
 
@@ -376,7 +376,7 @@
 
         if (!isVerticalLayout) {
             int expectedWorkspaceHeight = availableHeightPx - hotseatBarSizePx
-                    - verticalDragHandleSizePx - edgeMarginPx;
+                    - workspacePageIndicatorHeight - edgeMarginPx;
             float minRequiredHeight = dropTargetBarSizePx + workspaceSpringLoadedBottomSpace;
             workspaceSpringLoadShrinkFactor = Math.min(
                     res.getInteger(R.integer.config_workspaceSpringLoadShrinkPercentage) / 100.0f,
@@ -480,14 +480,14 @@
             padding.bottom = edgeMarginPx;
             if (isSeascape()) {
                 padding.left = hotseatBarSizePx;
-                padding.right = verticalDragHandleSizePx;
+                padding.right = hotseatBarSidePaddingStartPx;
             } else {
-                padding.left = verticalDragHandleSizePx;
+                padding.left = hotseatBarSidePaddingStartPx;
                 padding.right = hotseatBarSizePx;
             }
         } else {
-            int paddingBottom = hotseatBarSizePx + verticalDragHandleSizePx
-                    - verticalDragHandleOverlapWorkspace;
+            int paddingBottom = hotseatBarSizePx + workspacePageIndicatorHeight
+                    - mWorkspacePageIndicatorOverlapWorkspace;
             if (isTablet) {
                 // Pad the left and right of the workspace to ensure consistent spacing
                 // between all icons
@@ -554,7 +554,7 @@
                     mInsets.top + dropTargetBarSizePx + edgeMarginPx,
                     mInsets.left + availableWidthPx - edgeMarginPx,
                     mInsets.top + availableHeightPx - hotseatBarSizePx
-                            - verticalDragHandleSizePx - edgeMarginPx);
+                            - workspacePageIndicatorHeight - edgeMarginPx);
         }
     }
 
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index 7600f52..00128eb 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -123,8 +123,8 @@
 
         // Use a light system UI (dark icons) if all apps is behind at least half of the
         // status bar.
-        boolean forceChange = shiftCurrent - mScrimView.getDragHandleSize()
-                <= mLauncher.getDeviceProfile().getInsets().top / 2;
+        boolean forceChange = Math.min(shiftCurrent, mScrimView.getVisualTop())
+                <= mLauncher.getDeviceProfile().getInsets().top / 2f;
         if (forceChange) {
             mLauncher.getSystemUiController().updateUiState(UI_STATE_ALL_APPS, !mIsDarkTheme);
         } else {
diff --git a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
index 0f2ca72..408796f 100644
--- a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
@@ -121,7 +121,7 @@
         mLinePaint.setAlpha(0);
 
         mLauncher = Launcher.getLauncher(context);
-        mLineHeight = res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_line_height);
+        mLineHeight = res.getDimensionPixelSize(R.dimen.workspace_page_indicator_line_height);
 
         boolean darkText = WallpaperColorInfo.INSTANCE.get(context).supportsDarkText();
         mActiveAlpha = darkText ? BLACK_ALPHA : WHITE_ALPHA;
diff --git a/src/com/android/launcher3/views/ScrimView.java b/src/com/android/launcher3/views/ScrimView.java
index 6d204f6..adad097 100644
--- a/src/com/android/launcher3/views/ScrimView.java
+++ b/src/com/android/launcher3/views/ScrimView.java
@@ -33,8 +33,10 @@
 import android.animation.PropertyValuesHolder;
 import android.animation.RectEvaluator;
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Point;
 import android.graphics.Rect;
 import android.graphics.RectF;
 import android.graphics.drawable.Drawable;
@@ -115,7 +117,9 @@
     protected int mEndFlatColor;
     protected int mEndFlatColorAlpha;
 
-    protected final int mDragHandleSize;
+    protected final Point mDragHandleSize;
+    private final int mDragHandleTouchSize;
+    private final int mDragHandlePaddingInVerticalBarLayout;
     protected float mDragHandleOffset;
     private final Rect mDragHandleBounds;
     private final RectF mHitRect = new RectF();
@@ -136,9 +140,13 @@
 
         mMaxScrimAlpha = 0.7f;
 
-        mDragHandleSize = context.getResources()
-                .getDimensionPixelSize(R.dimen.vertical_drag_handle_size);
-        mDragHandleBounds = new Rect(0, 0, mDragHandleSize, mDragHandleSize);
+        Resources res = context.getResources();
+        mDragHandleSize = new Point(res.getDimensionPixelSize(R.dimen.vertical_drag_handle_width),
+                res.getDimensionPixelSize(R.dimen.vertical_drag_handle_height));
+        mDragHandleBounds = new Rect(0, 0, mDragHandleSize.x, mDragHandleSize.y);
+        mDragHandleTouchSize = res.getDimensionPixelSize(R.dimen.vertical_drag_handle_touch_size);
+        mDragHandlePaddingInVerticalBarLayout = context.getResources()
+                .getDimensionPixelSize(R.dimen.vertical_drag_handle_padding_in_vertical_bar_layout);
 
         mAccessibilityHelper = createAccessibilityHelper();
         ViewCompat.setAccessibilityDelegate(this, mAccessibilityHelper);
@@ -297,24 +305,26 @@
         DeviceProfile grid = mLauncher.getDeviceProfile();
         final int left;
         final int width = getMeasuredWidth();
-        final int top = getMeasuredHeight() - mDragHandleSize - grid.getInsets().bottom;
+        final int top = getMeasuredHeight() - mDragHandleSize.y - grid.getInsets().bottom;
         final int topMargin;
 
         if (grid.isVerticalBarLayout()) {
-            topMargin = grid.workspacePadding.bottom;
+            topMargin = grid.workspacePadding.bottom + mDragHandlePaddingInVerticalBarLayout;
             if (grid.isSeascape()) {
-                left = width - grid.getInsets().right - mDragHandleSize;
+                left = width - grid.getInsets().right - mDragHandleSize.x
+                        - mDragHandlePaddingInVerticalBarLayout;
             } else {
-                left = mDragHandleSize + grid.getInsets().left;
+                left = grid.getInsets().left + mDragHandlePaddingInVerticalBarLayout;
             }
         } else {
-            left = (width - mDragHandleSize) / 2;
+            left = Math.round((width - mDragHandleSize.x) / 2f);
             topMargin = grid.hotseatBarSizePx;
         }
         mDragHandleBounds.offsetTo(left, top - topMargin);
         mHitRect.set(mDragHandleBounds);
-        float inset = -mDragHandleSize / 2;
-        mHitRect.inset(inset, inset);
+        // Inset outwards to increase touch size.
+        mHitRect.inset((mDragHandleSize.x - mDragHandleTouchSize) / 2f,
+                (mDragHandleSize.y - mDragHandleTouchSize) / 2f);
 
         if (mDragHandle != null) {
             mDragHandle.setBounds(mDragHandleBounds);
@@ -341,7 +351,7 @@
         if (visible != wasVisible) {
             if (visible) {
                 mDragHandle = recycle != null ? recycle :
-                        mLauncher.getDrawable(R.drawable.drag_handle_indicator);
+                        mLauncher.getDrawable(R.drawable.drag_handle_indicator_shadow);
                 mDragHandle.setBounds(mDragHandleBounds);
 
                 updateDragHandleAlpha();
@@ -397,7 +407,7 @@
 
         @Override
         protected int getVirtualViewAt(float x, float y) {
-            return  mDragHandleBounds.contains((int) x, (int) y)
+            return  mHitRect.contains((int) x, (int) y)
                     ? DRAG_HANDLE_ID : INVALID_ID;
         }
 
@@ -470,7 +480,10 @@
         }
     }
 
-    public int getDragHandleSize() {
-        return mDragHandleSize;
+    /**
+     * @return The top of this scrim view, or {@link Float#MAX_VALUE} if there's no distinct top.
+     */
+    public float getVisualTop() {
+        return Float.MAX_VALUE;
     }
 }