Add caret shaped all app pull up handle to page indicator.
b/28917826

> PageIndicator is also added in landscape
> Touch delegate allows the active touch area to be 36dp

Change-Id: If00f45fc88a13cd5a6759d771313439eb58561e3
diff --git a/res/drawable/ic_allapps_caret.xml b/res/drawable/ic_allapps_caret.xml
new file mode 100644
index 0000000..34d1882
--- /dev/null
+++ b/res/drawable/ic_allapps_caret.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+     Copyright (C) 2016 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:height="24dp"
+    android:viewportHeight="48.0"
+    android:viewportWidth="48.0"
+    android:width="24dp" >
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M14.83,30.83L24,21.66l9.17,9.17L36,28 24,16 12,28z"/>
+</vector>
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index d193e2f..8ebc303 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -53,6 +53,12 @@
             android:id="@+id/overview_panel"
             android:visibility="gone" />
 
+        <com.android.launcher3.pageindicators.PageIndicatorCaretLandscape
+            android:id="@+id/page_indicator"
+            android:layout_width="48dp"
+            android:layout_height="@dimen/dynamic_grid_page_indicator_height"
+            android:layout_gravity="bottom|left"/>
+
         <include layout="@layout/widgets_view"
             android:id="@+id/widgets_view"
             android:layout_width="match_parent"
diff --git a/res/layout-port/launcher.xml b/res/layout-port/launcher.xml
index 527ed54..d1c1b2b 100644
--- a/res/layout-port/launcher.xml
+++ b/res/layout-port/launcher.xml
@@ -52,7 +52,7 @@
 
         <!-- Keep these behind the workspace so that they are not visible when
              we go into AllApps -->
-        <com.android.launcher3.pageindicators.PageIndicatorLine
+        <com.android.launcher3.pageindicators.PageIndicatorLineCaret
             android:id="@+id/page_indicator"
             android:layout_width="match_parent"
             android:layout_height="@dimen/dynamic_grid_page_indicator_height" />
diff --git a/res/layout-sw720dp/launcher.xml b/res/layout-sw720dp/launcher.xml
index 184e688..33ad323 100644
--- a/res/layout-sw720dp/launcher.xml
+++ b/res/layout-sw720dp/launcher.xml
@@ -55,7 +55,7 @@
 
         <!-- Keep these behind the workspace so that they are not visible when
              we go into AllApps -->
-        <com.android.launcher3.pageindicators.PageIndicatorLine
+        <com.android.launcher3.pageindicators.PageIndicatorLineCaret
             android:id="@+id/page_indicator"
             android:layout_width="match_parent"
             android:layout_height="@dimen/dynamic_grid_page_indicator_height" />
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 64868f2..cda8c05 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -17,7 +17,9 @@
 <resources>
 <!-- Dynamic Grid -->
     <dimen name="dynamic_grid_edge_margin">6dp</dimen>
-    <dimen name="dynamic_grid_page_indicator_height">1dp</dimen>
+    <dimen name="dynamic_grid_page_indicator_height">24dp</dimen>
+    <dimen name="dynamic_grid_page_indicator_line_height">1dp</dimen>
+    <dimen name="dynamic_grid_page_indicator_extra_touch_height">12dp</dimen>
     <dimen name="dynamic_grid_icon_drawable_padding">4dp</dimen>
     <dimen name="dynamic_grid_workspace_page_spacing">8dp</dimen>
     <dimen name="dynamic_grid_overview_min_icon_zone_height">80dp</dimen>
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 4a550ed..86f22d5 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -457,17 +457,14 @@
         // Layout the page indicators
         View pageIndicator = launcher.findViewById(R.id.page_indicator);
         if (pageIndicator != null) {
-            if (hasVerticalBarLayout) {
-                // Hide the page indicators when we have vertical search/hotseat
-                pageIndicator.setVisibility(View.GONE);
-            } else {
+            lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams();
+            if (!hasVerticalBarLayout) {
                 // Put the page indicators above the hotseat
-                lp = (FrameLayout.LayoutParams) pageIndicator.getLayoutParams();
                 lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
                 lp.width = LayoutParams.WRAP_CONTENT;
                 lp.bottomMargin = hotseatBarHeightPx;
-                pageIndicator.setLayoutParams(lp);
             }
+            pageIndicator.setLayoutParams(lp);
         }
 
         // Layout the Overview Mode
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index a504250..87ac67d 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -113,7 +113,7 @@
 import com.android.launcher3.logging.LoggerUtils;
 import com.android.launcher3.logging.UserEventDispatcher;
 import com.android.launcher3.model.WidgetsModel;
-import com.android.launcher3.pageindicators.PageIndicatorLine;
+import com.android.launcher3.pageindicators.PageIndicator;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.PackageManagerHelper;
@@ -233,7 +233,7 @@
 
     @Thunk Workspace mWorkspace;
     private View mLauncherView;
-    private PageIndicatorLine mPageIndicator;
+    private PageIndicator mPageIndicator;
     @Thunk DragLayer mDragLayer;
     private DragController mDragController;
 
@@ -1346,7 +1346,7 @@
         mFocusHandler = mDragLayer.getFocusIndicatorHelper();
 
         mWorkspace = (Workspace) mDragLayer.findViewById(R.id.workspace);
-        mPageIndicator = (PageIndicatorLine) mDragLayer.findViewById(R.id.page_indicator);
+        mPageIndicator = (PageIndicator) mDragLayer.findViewById(R.id.page_indicator);
 
         mLauncherView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                 | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
@@ -2491,7 +2491,7 @@
             if (v instanceof FolderIcon) {
                 onClickFolderIcon(v);
             }
-        } else if (v == mAllAppsButton) {
+        } else if (v instanceof PageIndicator || v == mAllAppsButton) {
             onClickAllAppsButton(v);
         } else if (tag instanceof AppInfo) {
             startAppShortcutOrInfoActivity(v);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 85ba57c..69aceb7 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -75,7 +75,7 @@
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.folder.FolderIcon;
 import com.android.launcher3.logging.UserEventDispatcher;
-import com.android.launcher3.pageindicators.PageIndicatorLine;
+import com.android.launcher3.pageindicators.PageIndicator;
 import com.android.launcher3.userevent.nano.LauncherLogProto;
 import com.android.launcher3.userevent.nano.LauncherLogProto.Target;
 import com.android.launcher3.util.LongArrayMap;
@@ -2096,9 +2096,9 @@
 
     @Override
     public void onLauncherTransitionStart(Launcher l, boolean animated, boolean toWorkspace) {
-        if (mPageIndicator instanceof PageIndicatorLine) {
+        if (mPageIndicator instanceof PageIndicator) {
             boolean isNewStateSpringLoaded = mState == State.SPRING_LOADED;
-            ((PageIndicatorLine) mPageIndicator).setShouldAutoHide(!isNewStateSpringLoaded);
+            mPageIndicator.setShouldAutoHide(!isNewStateSpringLoaded);
             if (isNewStateSpringLoaded) {
                 // Show the page indicator at the same time as the rest of the transition.
                 showPageIndicatorAtCurrentScroll();
diff --git a/src/com/android/launcher3/pageindicators/PageIndicator.java b/src/com/android/launcher3/pageindicators/PageIndicator.java
index 7c59495..2209bb8 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicator.java
@@ -1,9 +1,26 @@
+/*
+ * Copyright (C) 2016 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.
+ */
 package com.android.launcher3.pageindicators;
 
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.View;
 
+import com.android.launcher3.dynamicui.ExtractedColors;
+
 /**
  * Base class for a page indicator.
  */
@@ -15,9 +32,9 @@
         super(context, attrs, defStyleAttr);
     }
 
-    public abstract void setScroll(int currentScroll, int totalScroll);
+    public void setScroll(int currentScroll, int totalScroll) {}
 
-    public abstract void setActiveMarker(int activePage);
+    public void setActiveMarker(int activePage) {}
 
     public void addMarker() {
         mNumPages++;
@@ -33,5 +50,9 @@
         onPageCountChanged();
     }
 
-    protected abstract void onPageCountChanged();
+    protected void onPageCountChanged() { }
+
+    public void setShouldAutoHide(boolean shouldAutoHide) {}
+
+    public void updateColor(ExtractedColors extractedColors) {}
 }
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorCaretLandscape.java b/src/com/android/launcher3/pageindicators/PageIndicatorCaretLandscape.java
new file mode 100644
index 0000000..0f9145d
--- /dev/null
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorCaretLandscape.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2016 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.
+ */
+package com.android.launcher3.pageindicators;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.dynamicui.ExtractedColors;
+
+/**
+ * Simply draws the caret drawable in the center. Used for the landscape layout.
+ */
+public class PageIndicatorCaretLandscape extends PageIndicator {
+    // all apps pull up handle drawable.
+    private final Drawable caretDrawable;
+
+    public PageIndicatorCaretLandscape(Context context) {
+        this(context, null);
+    }
+
+    public PageIndicatorCaretLandscape(Context context, AttributeSet attrs) {
+        this(context, attrs, 0);
+    }
+
+    public PageIndicatorCaretLandscape(Context context, AttributeSet attrs, int defStyle) {
+        super(context, attrs, defStyle);
+
+        Resources res = context.getResources();
+        caretDrawable = res.getDrawable(R.drawable.ic_allapps_caret);
+        Launcher l = (Launcher) context;
+        setOnTouchListener(l.getHapticFeedbackTouchListener());
+        setOnClickListener(l);
+        setOnFocusChangeListener(l.mFocusHandler);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        int size = bottom - top;
+        int l = (right - left) / 2 - size / 2;
+        caretDrawable.setBounds(l, 0, l + size, size);
+    }
+
+    @Override
+    protected void onDraw(Canvas canvas) {
+        caretDrawable.draw(canvas);
+    }
+}
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorLine.java b/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
similarity index 68%
rename from src/com/android/launcher3/pageindicators/PageIndicatorLine.java
rename to src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
index aec708c..7394426 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorLine.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
@@ -5,17 +5,24 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
 import android.os.Handler;
 import android.os.Looper;
 import android.support.v4.graphics.ColorUtils;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.Property;
+import android.view.TouchDelegate;
+import android.view.View;
 import android.view.ViewConfiguration;
 
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.dynamicui.ExtractedColors;
 
@@ -24,9 +31,11 @@
  *
  * The fraction is 1 / number of pages and the position is based on the progress of the page scroll.
  */
-public class PageIndicatorLine extends PageIndicator {
+public class PageIndicatorLineCaret extends PageIndicator {
     private static final String TAG = "PageIndicatorLine";
 
+    private static final int[] sTempCoords = new int[2];
+
     private static final int LINE_ANIMATE_DURATION = ViewConfiguration.getScrollBarFadeDuration();
     private static final int LINE_FADE_DELAY = ViewConfiguration.getScrollDefaultDelay();
     public static final int WHITE_ALPHA = (int) (0.70f * 255);
@@ -51,44 +60,50 @@
     private int mCurrentScroll;
     private int mTotalScroll;
     private Paint mLinePaint;
+    private Launcher mLauncher;
+    // all apps pull up handle drawable.
+    private final Drawable caretDrawable;
+    private final int mLineHeight;
+    private final Rect mTouchHitRect = new Rect();
+    private final int mTouchExtensionHeight;
 
-    private static final Property<PageIndicatorLine, Integer> PAINT_ALPHA
-            = new Property<PageIndicatorLine, Integer>(Integer.class, "paint_alpha") {
+    private static final Property<PageIndicatorLineCaret, Integer> PAINT_ALPHA
+            = new Property<PageIndicatorLineCaret, Integer>(Integer.class, "paint_alpha") {
         @Override
-        public Integer get(PageIndicatorLine obj) {
+        public Integer get(PageIndicatorLineCaret obj) {
             return obj.mLinePaint.getAlpha();
         }
 
         @Override
-        public void set(PageIndicatorLine obj, Integer alpha) {
+        public void set(PageIndicatorLineCaret obj, Integer alpha) {
             obj.mLinePaint.setAlpha(alpha);
             obj.invalidate();
         }
     };
 
-    private static final Property<PageIndicatorLine, Float> NUM_PAGES
-            = new Property<PageIndicatorLine, Float>(Float.class, "num_pages") {
+    private static final Property<PageIndicatorLineCaret, Float> NUM_PAGES
+            = new Property<PageIndicatorLineCaret, Float>(Float.class, "num_pages") {
         @Override
-        public Float get(PageIndicatorLine obj) {
+        public Float get(PageIndicatorLineCaret obj) {
             return obj.mNumPagesFloat;
         }
 
         @Override
-        public void set(PageIndicatorLine obj, Float numPages) {
+        public void set(PageIndicatorLineCaret obj, Float numPages) {
             obj.mNumPagesFloat = numPages;
             obj.invalidate();
         }
     };
 
-    private static final Property<PageIndicatorLine, Integer> TOTAL_SCROLL
-            = new Property<PageIndicatorLine, Integer>(Integer.class, "total_scroll") {
+    private static final Property<PageIndicatorLineCaret, Integer> TOTAL_SCROLL
+            = new Property<PageIndicatorLineCaret, Integer>(Integer.class, "total_scroll") {
         @Override
-        public Integer get(PageIndicatorLine obj) {
+        public Integer get(PageIndicatorLineCaret obj) {
             return obj.mTotalScroll;
         }
 
         @Override
-        public void set(PageIndicatorLine obj, Integer totalScroll) {
+        public void set(PageIndicatorLineCaret obj, Integer totalScroll) {
             obj.mTotalScroll = totalScroll;
             obj.invalidate();
         }
@@ -101,22 +116,50 @@
         }
     };
 
-    public PageIndicatorLine(Context context) {
+    public PageIndicatorLineCaret(Context context) {
         this(context, null);
     }
 
-    public PageIndicatorLine(Context context, AttributeSet attrs) {
+    public PageIndicatorLineCaret(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
     }
 
-    public PageIndicatorLine(Context context, AttributeSet attrs, int defStyle) {
+    public PageIndicatorLineCaret(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         mLinePaint = new Paint();
         mLinePaint.setAlpha(0);
+
+        mLauncher = (Launcher) context;
+        setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
+        setOnClickListener(mLauncher);
+        setOnFocusChangeListener(mLauncher.mFocusHandler);
+        Resources res = context.getResources();
+        caretDrawable = res.getDrawable(R.drawable.ic_allapps_caret);
+        mLineHeight = res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_line_height);
+        mTouchExtensionHeight = res.getDimensionPixelSize(
+                R.dimen.dynamic_grid_page_indicator_extra_touch_height);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        int size = bottom - top;
+        int l = (right - left) / 2 - size / 2;
+        caretDrawable.setBounds(l, 0, l+ size, size);
+
+        // The touch area is expanded below this view by #mTouchExtensionHeight
+        // which extends to the top of the hotseat.
+        View parent = mLauncher.getDragLayer();
+        sTempCoords[0] = sTempCoords[1] = 0;
+        Utilities.getDescendantCoordRelativeToParent(this, parent, sTempCoords, true);
+        mTouchHitRect.set(sTempCoords[0], sTempCoords[1], sTempCoords[0] + this.getWidth(),
+                sTempCoords[1] + getHeight() + mTouchExtensionHeight);
+        parent.setTouchDelegate(new TouchDelegate(mTouchHitRect, this));
     }
 
     @Override
     protected void onDraw(Canvas canvas) {
+        caretDrawable.draw(canvas);
         if (mTotalScroll == 0 || mNumPagesFloat == 0) {
             return;
         }
@@ -127,7 +170,8 @@
         int lineWidth = (int) (availableWidth / mNumPagesFloat);
         int lineLeft = (int) (progress * (availableWidth - lineWidth));
         int lineRight = lineLeft + lineWidth;
-        canvas.drawRect(lineLeft, 0, lineRight, canvas.getHeight(), mLinePaint);
+        canvas.drawRect(lineLeft, canvas.getHeight() + mLineHeight, lineRight, canvas.getHeight(),
+                mLinePaint);
     }
 
     @Override