Merge changes from topic 'am-9eed976f-7d63-45d0-ad0c-14ddd50e37d1' into ub-launcher3-dorval-polish2

* changes:
  Changes on the wallpaper gradient extraction algorithm:  fallback colors for very light or very dark luminosity. am: 97f93583d3
  Changes on the wallpaper gradient extraction algorithm:  fallback colors for very light or very dark luminosity.
diff --git a/res/layout-land/launcher.xml b/res/layout-land/launcher.xml
index e6f98a4..fd66593 100644
--- a/res/layout-land/launcher.xml
+++ b/res/layout-land/launcher.xml
@@ -60,13 +60,6 @@
             android:id="@+id/overview_panel"
             android:visibility="gone" />
 
-        <com.android.launcher3.pageindicators.PageIndicatorCaretLandscape
-            android:id="@+id/page_indicator"
-            android:theme="@style/HomeScreenElementTheme"
-            android:layout_width="@dimen/dynamic_grid_min_page_indicator_size"
-            android:layout_height="@dimen/dynamic_grid_min_page_indicator_size"
-            android:layout_gravity="bottom|left"/>
-
         <include layout="@layout/widgets_view"
             android:id="@+id/widgets_view"
             android:layout_width="match_parent"
@@ -79,6 +72,13 @@
             android:layout_height="match_parent"
             android:visibility="invisible" />
 
+        <com.android.launcher3.pageindicators.PageIndicatorCaretLandscape
+            android:id="@+id/page_indicator"
+            android:theme="@style/HomeScreenElementTheme"
+            android:layout_width="@dimen/dynamic_grid_min_page_indicator_size"
+            android:layout_height="@dimen/dynamic_grid_min_page_indicator_size"
+            android:layout_gravity="bottom|left"/>
+
     </com.android.launcher3.dragndrop.DragLayer>
 
 </com.android.launcher3.LauncherRootView>
diff --git a/res/values-land/dimens.xml b/res/values-land/dimens.xml
index 1d36f75..1ab385c 100644
--- a/res/values-land/dimens.xml
+++ b/res/values-land/dimens.xml
@@ -26,7 +26,7 @@
 
     <!-- Dynamic grid -->
     <dimen name="dynamic_grid_overview_bar_item_width">120dp</dimen>
-    <dimen name="dynamic_grid_min_page_indicator_size">24dp</dimen>
+    <dimen name="dynamic_grid_min_page_indicator_size">48dp</dimen>
     <dimen name="folder_preview_padding">5dp</dimen>
 
     <!-- Hotseat -->
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 0f4abbe..6b76cd6 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -597,15 +597,18 @@
                     ? hotseatBarLeftNavBarRightPaddingPx
                     : hotseatBarRightNavBarRightPaddingPx;
 
-            hotseat.getLayout().setPadding(mInsets.left, mInsets.top, mInsets.right + paddingRight,
+            hotseat.getLayout().setPadding(mInsets.left + cellLayoutPaddingLeftRightPx,
+                    mInsets.top, mInsets.right + paddingRight + cellLayoutPaddingLeftRightPx,
                     workspacePadding.bottom);
         } else if (isTablet) {
             // Pad the hotseat with the workspace padding calculated above
             lp.gravity = Gravity.BOTTOM;
             lp.width = LayoutParams.MATCH_PARENT;
             lp.height = hotseatBarHeightPx + mInsets.bottom;
-            hotseat.getLayout().setPadding(hotseatAdjustment + workspacePadding.left,
-                    hotseatBarTopPaddingPx, hotseatAdjustment + workspacePadding.right,
+            hotseat.getLayout().setPadding(hotseatAdjustment + workspacePadding.left
+                            + cellLayoutPaddingLeftRightPx,
+                    hotseatBarTopPaddingPx,
+                    hotseatAdjustment + workspacePadding.right + cellLayoutPaddingLeftRightPx,
                     hotseatBarBottomPaddingPx + mInsets.bottom);
         } else {
             // For phones, layout the hotseat without any bottom margin
@@ -613,11 +616,12 @@
             lp.gravity = Gravity.BOTTOM;
             lp.width = LayoutParams.MATCH_PARENT;
             lp.height = hotseatBarHeightPx + mInsets.bottom;
-            hotseat.getLayout().setPadding(hotseatAdjustment + workspacePadding.left,
-                    hotseatBarTopPaddingPx, hotseatAdjustment + workspacePadding.right,
+            hotseat.getLayout().setPadding(hotseatAdjustment + workspacePadding.left
+                            + cellLayoutPaddingLeftRightPx,
+                    hotseatBarTopPaddingPx,
+                    hotseatAdjustment + workspacePadding.right + cellLayoutPaddingLeftRightPx,
                     hotseatBarBottomPaddingPx + mInsets.bottom);
         }
-        hotseat.setPadding(cellLayoutPaddingLeftRightPx, 0, cellLayoutPaddingLeftRightPx, 0);
         hotseat.setLayoutParams(lp);
 
         // Layout the page indicators
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 6ae4068..6ab50f6 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2256,8 +2256,9 @@
             if (v instanceof FolderIcon) {
                 onClickFolderIcon(v);
             }
-        } else if ((FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && v instanceof PageIndicator) ||
-                (v == mAllAppsButton && mAllAppsButton != null)) {
+        } else if ((FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP && v instanceof PageIndicator)) {
+            onClickAllAppsCaret(v);
+        } else if (v == mAllAppsButton && mAllAppsButton != null) {
             onClickAllAppsButton(v);
         } else if (tag instanceof AppInfo) {
             startAppShortcutOrInfoActivity(v);
@@ -2322,6 +2323,22 @@
         }
     }
 
+    /**
+     * Event handler for the swipe up caret
+     *
+     * @param v The view that was clicked.
+     */
+    protected void onClickAllAppsCaret(View v) {
+        if (LOGD) Log.d(TAG, "onClickAllAppsCaret");
+        if (!isAppsViewVisible()) {
+            getUserEventDispatcher().logActionOnControl(Action.Touch.TAP,
+                    ControlType.ALL_APPS_BUTTON);
+            showAppsView(true /* animated */, true /* updatePredictedApps */);
+        } else {
+            showWorkspace(true);
+        }
+    }
+
     private void onClickPendingAppItem(final View v, final String packageName,
             boolean downloadStarted) {
         if (downloadStarted) {
diff --git a/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java b/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java
index ff357c0..f25345e 100644
--- a/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java
+++ b/src/com/android/launcher3/folder/ClippedFolderIconLayoutRule.java
@@ -1,15 +1,18 @@
 package com.android.launcher3.folder;
 
+
 public class ClippedFolderIconLayoutRule implements FolderIcon.PreviewLayoutRule {
 
     static final int MAX_NUM_ITEMS_IN_PREVIEW = 4;
     private static final int MIN_NUM_ITEMS_IN_PREVIEW = 2;
-    private static final int MAX_NUM_ITEMS_PER_ROW = 2;
 
-    final float MIN_SCALE = 0.48f;
-    final float MAX_SCALE = 0.58f;
-    final float MAX_RADIUS_DILATION = 0.15f;
-    final float ITEM_RADIUS_SCALE_FACTOR = 1.33f;
+    private static final float MIN_SCALE = 0.48f;
+    private static final float MAX_SCALE = 0.58f;
+    private static final float MAX_RADIUS_DILATION = 0.15f;
+    private static final float ITEM_RADIUS_SCALE_FACTOR = 1.33f;
+
+    private static final int EXIT_INDEX = -2;
+    private static final int ENTER_INDEX = -3;
 
     private float[] mTmpPoint = new float[2];
 
@@ -31,21 +34,29 @@
     @Override
     public PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
             PreviewItemDrawingParams params) {
-
         float totalScale = scaleForItem(index, curNumItems);
         float transX;
         float transY;
         float overlayAlpha = 0;
 
-        // Items beyond those displayed in the preview are animated to the center
-        if (index >= MAX_NUM_ITEMS_IN_PREVIEW) {
-            transX = transY = mAvailableSpace / 2 - (mIconSize * totalScale) / 2;
+        if (index == getExitIndex()) {
+            // 0 1 * <-- Exit position (row 0, col 2)
+            // 2 3
+            getGridPosition(0, 2, mTmpPoint);
+        } else if (index == getEnterIndex()) {
+            // 0 1
+            // 2 3 * <-- Enter position (row 1, col 2)
+            getGridPosition(1, 2, mTmpPoint);
+        } else if (index >= MAX_NUM_ITEMS_IN_PREVIEW) {
+            // Items beyond those displayed in the preview are animated to the center
+            mTmpPoint[0] = mTmpPoint[1] = mAvailableSpace / 2 - (mIconSize * totalScale) / 2;
         } else {
             getPosition(index, curNumItems, mTmpPoint);
-            transX = mTmpPoint[0];
-            transY = mTmpPoint[1];
         }
 
+        transX = mTmpPoint[0];
+        transY = mTmpPoint[1];
+
         if (params == null) {
             params = new PreviewItemDrawingParams(transX, transY, totalScale, overlayAlpha);
         } else {
@@ -55,6 +66,27 @@
         return params;
     }
 
+    /**
+     * Builds a grid based on the positioning of the items when there are
+     * {@link #MAX_NUM_ITEMS_IN_PREVIEW} in the preview.
+     *
+     * Positions in the grid: 0 1  // 0 is row 0, col 1
+     *                        2 3  // 3 is row 1, col 1
+     */
+    private void getGridPosition(int row, int col, float[] result) {
+        // We use position 0 and 3 to calculate the x and y distances between items.
+        getPosition(0, 4, result);
+        float left = result[0];
+        float top = result[1];
+
+        getPosition(3, 4, result);
+        float dx = result[0] - left;
+        float dy = result[1] - top;
+
+        result[0] = left + (col * dx);
+        result[1] = top + (row * dy);
+    }
+
     private void getPosition(int index, int curNumItems, float[] result) {
         // The case of two items is homomorphic to the case of one.
         curNumItems = Math.max(curNumItems, 2);
@@ -127,4 +159,19 @@
     public boolean clipToBackground() {
         return true;
     }
+
+    @Override
+    public boolean hasEnterExitIndices() {
+        return true;
+    }
+
+    @Override
+    public int getExitIndex() {
+        return EXIT_INDEX;
+    }
+
+    @Override
+    public int getEnterIndex() {
+        return ENTER_INDEX;
+    }
 }
diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java
index 26a2c89..69705d5 100644
--- a/src/com/android/launcher3/folder/FolderAnimationManager.java
+++ b/src/com/android/launcher3/folder/FolderAnimationManager.java
@@ -125,7 +125,8 @@
         final Rect folderIconPos = new Rect();
         float scaleRelativeToDragLayer = mLauncher.getDragLayer()
                 .getDescendantRectRelativeToSelf(mFolderIcon, folderIconPos);
-        float initialSize = (mPreviewBackground.getRadius() * 2) * scaleRelativeToDragLayer;
+        int scaledRadius = mPreviewBackground.getScaledRadius();
+        float initialSize = (scaledRadius * 2) * scaleRelativeToDragLayer;
 
         // Match size/scale of icons in the preview
         float previewScale = rule.scaleForItem(0, itemsInPreview.size());
@@ -152,13 +153,9 @@
         final int paddingOffsetY = (int) ((mFolder.getPaddingTop() + mContent.getPaddingTop())
                 * initialScale);
 
-        // Background can have a scaled radius in drag and drop mode.
-        int radiusDiff = mPreviewBackground.getScaledRadius()- mPreviewBackground.getRadius();
-
         int initialX = folderIconPos.left + mPreviewBackground.getOffsetX() - paddingOffsetX
-                - previewItemOffsetX + radiusDiff;
-        int initialY = folderIconPos.top + mPreviewBackground.getOffsetY() - paddingOffsetY
-                + radiusDiff;
+                - previewItemOffsetX;
+        int initialY = folderIconPos.top + mPreviewBackground.getOffsetY() - paddingOffsetY;
         final float xDistance = initialX - lp.x;
         final float yDistance = initialY - lp.y;
 
@@ -232,7 +229,11 @@
             animator.setInterpolator(mFolderInterpolator);
         }
 
-        addPreviewItemAnimators(a, initialScale / scaleRelativeToDragLayer, previewItemOffsetX);
+        int radiusDiff = scaledRadius - mPreviewBackground.getRadius();
+        addPreviewItemAnimators(a, initialScale / scaleRelativeToDragLayer,
+                // Background can have a scaled radius in drag and drop mode, so we need to add the
+                // difference to keep the preview items centered.
+                previewItemOffsetX + radiusDiff, radiusDiff);
         return a;
     }
 
@@ -240,7 +241,7 @@
      * Animate the items on the current page.
      */
     private void addPreviewItemAnimators(AnimatorSet animatorSet, final float folderScale,
-            int previewItemOffsetX) {
+            int previewItemOffsetX, int previewItemOffsetY) {
         FolderIcon.PreviewLayoutRule rule = mFolderIcon.getLayoutRule();
         boolean isOnFirstPage = mFolder.mContent.getCurrentPage() == 0;
         final List<BubbleTextView> itemsInPreview = isOnFirstPage
@@ -281,7 +282,7 @@
 
             final int previewPosX =
                     (int) ((mTmpParams.transX - iconOffsetX + previewItemOffsetX) / folderScale);
-            final int previewPosY = (int) (mTmpParams.transY / folderScale);
+            final int previewPosY = (int) ((mTmpParams.transY + previewItemOffsetY) / folderScale);
 
             final float xDistance = previewPosX - btvLp.x;
             final float yDistance = previewPosY - btvLp.y;
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index ae6a0e8..c63eeb3 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -221,7 +221,15 @@
     }
 
     public void addItem(ShortcutInfo item) {
-        mInfo.add(item, true);
+        addItem(item, true);
+    }
+
+    public void addItem(ShortcutInfo item, boolean animate) {
+        mInfo.add(item, animate);
+    }
+
+    public void removeItem(ShortcutInfo item, boolean animate) {
+        mInfo.remove(item, animate);
     }
 
     public void onDragEnter(ItemInfo dragInfo) {
@@ -276,7 +284,7 @@
     }
 
     private void onDrop(final ShortcutInfo item, DragView animateView, Rect finalRect,
-            float scaleRelativeToDragLayer, final int index, Runnable postAnimationRunnable) {
+            float scaleRelativeToDragLayer, int index, Runnable postAnimationRunnable) {
         item.cellX = -1;
         item.cellY = -1;
 
@@ -304,13 +312,39 @@
                 workspace.resetTransitionTransform((CellLayout) getParent().getParent());
             }
 
+            boolean itemAdded = false;
+            if (index >= mPreviewLayoutRule.maxNumItems()
+                    && mPreviewLayoutRule.hasEnterExitIndices()) {
+                List<BubbleTextView> oldPreviewItems = getPreviewItemsOnPage(0);
+                addItem(item, false);
+                List<BubbleTextView> newPreviewItems = getPreviewItemsOnPage(0);
+
+                if (!oldPreviewItems.containsAll(newPreviewItems)) {
+                    for (int i = 0; i < newPreviewItems.size(); ++i) {
+                        if (newPreviewItems.get(i).getTag().equals(item)) {
+                            // If the item dropped is going to be in the preview, we update the
+                            // index here to reflect its position in the preview.
+                            index = i;
+                        }
+                    }
+                    mPreviewItemManager.onDrop(oldPreviewItems, newPreviewItems, item);
+                    itemAdded = true;
+                } else {
+                    removeItem(item, false);
+                }
+            }
+
+            if (!itemAdded) {
+                addItem(item);
+            }
+
             int[] center = new int[2];
             float scale = getLocalCenterForIndex(index, index + 1, center);
             center[0] = (int) Math.round(scaleRelativeToDragLayer * center[0]);
             center[1] = (int) Math.round(scaleRelativeToDragLayer * center[1]);
 
             to.offset(center[0] - animateView.getMeasuredWidth() / 2,
-                      center[1] - animateView.getMeasuredHeight() / 2);
+                    center[1] - animateView.getMeasuredHeight() / 2);
 
             float finalAlpha = index < mPreviewLayoutRule.maxNumItems() ? 0.5f : 0f;
 
@@ -319,13 +353,14 @@
                     1, 1, finalScale, finalScale, DROP_IN_ANIMATION_DURATION,
                     new DecelerateInterpolator(2), new AccelerateInterpolator(2),
                     postAnimationRunnable, DragLayer.ANIMATION_END_DISAPPEAR, null);
-            addItem(item);
+
             mFolder.hideItem(item);
 
-            mPreviewItemManager.hidePreviewItem(index, true);
+            if (!itemAdded) mPreviewItemManager.hidePreviewItem(index, true);
+            final int finalIndex = index;
             postDelayed(new Runnable() {
                 public void run() {
-                    mPreviewItemManager.hidePreviewItem(index, false);
+                    mPreviewItemManager.hidePreviewItem(finalIndex, false);
                     mFolder.showItem(item);
                     invalidate();
                 }
@@ -655,11 +690,16 @@
 
     interface PreviewLayoutRule {
         PreviewItemDrawingParams computePreviewItemDrawingParams(int index, int curNumItems,
-            PreviewItemDrawingParams params);
+                PreviewItemDrawingParams params);
         void init(int availableSpace, float intrinsicIconSize, boolean rtl);
         float scaleForItem(int index, int totalNumItems);
         float getIconSize();
         int maxNumItems();
         boolean clipToBackground();
+
+        boolean hasEnterExitIndices();
+        int getExitIndex();
+        int getEnterIndex();
+
     }
 }
diff --git a/src/com/android/launcher3/folder/FolderIconPreviewVerifier.java b/src/com/android/launcher3/folder/FolderIconPreviewVerifier.java
index 11c1078..d054a5d 100644
--- a/src/com/android/launcher3/folder/FolderIconPreviewVerifier.java
+++ b/src/com/android/launcher3/folder/FolderIconPreviewVerifier.java
@@ -40,19 +40,14 @@
     }
 
     public void setFolderInfo(FolderInfo info) {
-        FolderPagedView.calculateGridSize(info.contents.size(), 0, 0, mMaxGridCountX,
+        int numItemsInFolder = info.contents.size();
+        FolderPagedView.calculateGridSize(numItemsInFolder, 0, 0, mMaxGridCountX,
                 mMaxGridCountY, mMaxItemsPerPage, mGridSize);
         mGridCountX = mGridSize[0];
-        int numItemsInFolder = info.contents.size();
+
         mDisplayingUpperLeftQuadrant = FeatureFlags.LAUNCHER3_NEW_FOLDER_ANIMATION
                 && !FeatureFlags.LAUNCHER3_LEGACY_FOLDER_ICON
                 && numItemsInFolder > FolderIcon.NUM_ITEMS_IN_PREVIEW;
-
-        if (mDisplayingUpperLeftQuadrant) {
-            FolderPagedView.calculateGridSize(info.contents.size(), 0, 0, mMaxGridCountX,
-                    mMaxGridCountY, mMaxItemsPerPage, mGridSize);
-            mGridCountX = mGridSize[0];
-        }
     }
 
     /**
diff --git a/src/com/android/launcher3/folder/PreviewItemManager.java b/src/com/android/launcher3/folder/PreviewItemManager.java
index 74c2102..7a05f67 100644
--- a/src/com/android/launcher3/folder/PreviewItemManager.java
+++ b/src/com/android/launcher3/folder/PreviewItemManager.java
@@ -27,6 +27,7 @@
 import android.widget.TextView;
 
 import com.android.launcher3.BubbleTextView;
+import com.android.launcher3.ShortcutInfo;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.config.FeatureFlags;
 
@@ -273,4 +274,80 @@
     float getIntrinsicIconSize() {
         return mIntrinsicIconSize;
     }
+
+    /**
+     * Handles the case where items in the preview are either:
+     *  - Moving into the preview
+     *  - Moving into a new position
+     *  - Moving out of the preview
+     *
+     * @param oldParams The list of items in the old preview.
+     * @param newParams The list of items in the new preview.
+     * @param dropped The item that was dropped onto the FolderIcon.
+     */
+    public void onDrop(List<BubbleTextView> oldParams, List<BubbleTextView> newParams,
+            ShortcutInfo dropped) {
+        int numItems = newParams.size();
+        final ArrayList<PreviewItemDrawingParams> params = mFirstPageParams;
+        buildParamsForPage(0, params, false);
+
+        // New preview items for items that are moving in (except for the dropped item).
+        List<BubbleTextView> moveIn = new ArrayList<>();
+        for (BubbleTextView btv : newParams) {
+            if (!oldParams.contains(btv) && !btv.getTag().equals(dropped)) {
+                moveIn.add(btv);
+            }
+        }
+        for (int i = 0; i < moveIn.size(); ++i) {
+            int prevIndex = newParams.indexOf(moveIn.get(i));
+            PreviewItemDrawingParams p = params.get(prevIndex);
+            computePreviewItemDrawingParams(prevIndex, numItems, p);
+            updateTransitionParam(p, moveIn.get(i), mIcon.mPreviewLayoutRule.getEnterIndex(),
+                    newParams.indexOf(moveIn.get(i)));
+        }
+
+        // Items that are moving into new positions within the preview.
+        for (int newIndex = 0; newIndex < newParams.size(); ++newIndex) {
+            int oldIndex = oldParams.indexOf(newParams.get(newIndex));
+            if (oldIndex >= 0 && newIndex != oldIndex) {
+                PreviewItemDrawingParams p = params.get(newIndex);
+                updateTransitionParam(p, newParams.get(newIndex), oldIndex, newIndex);
+            }
+        }
+
+        // Old preview items that need to be moved out.
+        List<BubbleTextView> moveOut = new ArrayList<>(oldParams);
+        moveOut.removeAll(newParams);
+        for (int i = 0; i < moveOut.size(); ++i) {
+            BubbleTextView item = moveOut.get(i);
+            int oldIndex = oldParams.indexOf(item);
+            PreviewItemDrawingParams p = computePreviewItemDrawingParams(oldIndex, numItems, null);
+            updateTransitionParam(p, item, oldIndex, mIcon.mPreviewLayoutRule.getExitIndex());
+            params.add(0, p); // We want these items first so that they are on drawn last.
+        }
+
+        for (int i = 0; i < params.size(); ++i) {
+            if (params.get(i).anim != null) {
+                params.get(i).anim.start();
+            }
+        }
+    }
+
+    private void updateTransitionParam(final PreviewItemDrawingParams p, BubbleTextView btv,
+            int prevIndex, int newIndex) {
+        p.drawable = btv.getCompoundDrawables()[1];
+        if (!mIcon.mFolder.isOpen()) {
+            // Set the callback to FolderIcon as it is responsible to drawing the icon. The
+            // callback will be released when the folder is opened.
+            p.drawable.setCallback(mIcon);
+        }
+
+        FolderPreviewItemAnim anim = new FolderPreviewItemAnim(this, p, prevIndex,
+                FolderIcon.NUM_ITEMS_IN_PREVIEW, newIndex, FolderIcon.NUM_ITEMS_IN_PREVIEW,
+                DROP_IN_ANIMATION_DURATION, null);
+        if (p.anim != null && !p.anim.hasEqualFinalState(anim)) {
+            p.anim.cancel();
+        }
+        p.anim = anim;
+    }
 }
diff --git a/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java b/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java
index 138dc1c..7d10556 100644
--- a/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java
+++ b/src/com/android/launcher3/folder/StackFolderIconLayoutRule.java
@@ -97,4 +97,19 @@
     public boolean clipToBackground() {
         return false;
     }
+
+    @Override
+    public boolean hasEnterExitIndices() {
+        return false;
+    }
+
+    @Override
+    public int getExitIndex() {
+        throw new RuntimeException("hasEnterExitIndices not supported");
+    }
+
+    @Override
+    public int getEnterIndex() {
+        throw new RuntimeException("hasEnterExitIndices not supported");
+    }
 }
diff --git a/src/com/android/launcher3/notification/NotificationListener.java b/src/com/android/launcher3/notification/NotificationListener.java
index 8121fd5..73d89aa 100644
--- a/src/com/android/launcher3/notification/NotificationListener.java
+++ b/src/com/android/launcher3/notification/NotificationListener.java
@@ -28,6 +28,7 @@
 import android.support.annotation.Nullable;
 import android.text.TextUtils;
 import android.util.ArraySet;
+import android.util.Log;
 import android.util.Pair;
 import com.android.launcher3.LauncherModel;
 import com.android.launcher3.config.FeatureFlags;
@@ -47,6 +48,8 @@
 @TargetApi(Build.VERSION_CODES.O)
 public class NotificationListener extends NotificationListenerService {
 
+    public static final String TAG = "NotificationListener";
+
     private static final int MSG_NOTIFICATION_POSTED = 1;
     private static final int MSG_NOTIFICATION_REMOVED = 2;
     private static final int MSG_NOTIFICATION_FULL_REFRESH = 3;
@@ -71,9 +74,19 @@
                     mUiHandler.obtainMessage(message.what, message.obj).sendToTarget();
                     break;
                 case MSG_NOTIFICATION_FULL_REFRESH:
-                    final List<StatusBarNotification> activeNotifications = sIsConnected
-                            ? filterNotifications(getActiveNotifications())
-                            : new ArrayList<StatusBarNotification>();
+                    List<StatusBarNotification> activeNotifications;
+                    if (sIsConnected) {
+                        try {
+                            activeNotifications =  filterNotifications(getActiveNotifications());
+                        } catch (SecurityException ex) {
+                            Log.e(TAG, "SecurityException: failed to fetch notifications");
+                            activeNotifications = new ArrayList<StatusBarNotification>();
+
+                        }
+                    } else {
+                        activeNotifications = new ArrayList<StatusBarNotification>();
+                    }
+
                     mUiHandler.obtainMessage(message.what, activeNotifications).sendToTarget();
                     break;
             }
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorCaretLandscape.java b/src/com/android/launcher3/pageindicators/PageIndicatorCaretLandscape.java
index 8bcb979..682d5a9 100644
--- a/src/com/android/launcher3/pageindicators/PageIndicatorCaretLandscape.java
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorCaretLandscape.java
@@ -57,7 +57,7 @@
     protected void onDraw(Canvas canvas) {
         Rect drawableBounds = getCaretDrawable().getBounds();
         int count = canvas.save();
-        canvas.translate(getWidth() - drawableBounds.width(),
+        canvas.translate((getWidth() - drawableBounds.width()) / 2,
                 getHeight() - drawableBounds.height());
         getCaretDrawable().draw(canvas);
         canvas.restoreToCount(count);