Merge "Updating the widget error view" into ub-launcher3-burnaby
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
index affad0f..ee0d8b0 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperCropActivity.java
@@ -131,7 +131,7 @@
 
         // Load image in background
         final BitmapRegionTileSource.UriBitmapSource bitmapSource =
-                new BitmapRegionTileSource.UriBitmapSource(getContext(), imageUri, 1024);
+                new BitmapRegionTileSource.UriBitmapSource(getContext(), imageUri);
         mSetWallpaperButton.setEnabled(false);
         Runnable onLoad = new Runnable() {
             public void run() {
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index 1ba5b4b..72cb194 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -21,7 +21,6 @@
 import android.app.ActionBar;
 import android.app.Activity;
 import android.app.WallpaperManager;
-import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
@@ -144,8 +143,7 @@
         public void onClick(final WallpaperPickerActivity a) {
             a.setWallpaperButtonEnabled(false);
             final BitmapRegionTileSource.UriBitmapSource bitmapSource =
-                    new BitmapRegionTileSource.UriBitmapSource(
-                            a.getContext(), mUri, BitmapRegionTileSource.MAX_PREVIEW_SIZE);
+                    new BitmapRegionTileSource.UriBitmapSource(a.getContext(), mUri);
             a.setCropViewTileSource(bitmapSource, true, false, null, new Runnable() {
 
                 @Override
@@ -199,8 +197,7 @@
         public void onClick(final WallpaperPickerActivity a) {
             a.setWallpaperButtonEnabled(false);
             BitmapRegionTileSource.UriBitmapSource bitmapSource =
-                    new BitmapRegionTileSource.UriBitmapSource(a.getContext(),
-                            Uri.fromFile(mFile), 1024);
+                    new BitmapRegionTileSource.UriBitmapSource(a.getContext(), Uri.fromFile(mFile));
             a.setCropViewTileSource(bitmapSource, false, true, null, new Runnable() {
 
                 @Override
@@ -236,8 +233,7 @@
         public void onClick(final WallpaperPickerActivity a) {
             a.setWallpaperButtonEnabled(false);
             BitmapRegionTileSource.ResourceBitmapSource bitmapSource =
-                    new BitmapRegionTileSource.ResourceBitmapSource(
-                            mResources, mResId, BitmapRegionTileSource.MAX_PREVIEW_SIZE);
+                    new BitmapRegionTileSource.ResourceBitmapSource(mResources, mResId);
             a.setCropViewTileSource(bitmapSource, false, false, new CropViewScaleProvider() {
 
                 @Override
diff --git a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
index 15f97e5..2d496a5 100644
--- a/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
+++ b/WallpaperPicker/src/com/android/photos/BitmapRegionTileSource.java
@@ -26,6 +26,7 @@
 import android.graphics.Paint;
 import android.graphics.Rect;
 import android.net.Uri;
+import android.opengl.GLUtils;
 import android.os.Build;
 import android.util.Log;
 
@@ -149,18 +150,15 @@
     private static final int GL_SIZE_LIMIT = 2048;
     // This must be no larger than half the size of the GL_SIZE_LIMIT
     // due to decodePreview being allowed to be up to 2x the size of the target
-    public static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2;
+    private static final int MAX_PREVIEW_SIZE = GL_SIZE_LIMIT / 2;
 
     public static abstract class BitmapSource {
         private SimpleBitmapRegionDecoder mDecoder;
         private Bitmap mPreview;
-        private final int mPreviewSize;
         private int mRotation;
         public enum State { NOT_LOADED, LOADED, ERROR_LOADING };
         private State mState = State.NOT_LOADED;
-        public BitmapSource(int previewSize) {
-            mPreviewSize = Math.min(previewSize, MAX_PREVIEW_SIZE);
-        }
+
         public boolean loadInBackground(InBitmapProvider bitmapProvider) {
             ExifInterface ei = new ExifInterface();
             if (readExif(ei)) {
@@ -176,36 +174,44 @@
             } else {
                 int width = mDecoder.getWidth();
                 int height = mDecoder.getHeight();
-                if (mPreviewSize != 0) {
-                    BitmapFactory.Options opts = new BitmapFactory.Options();
-                    opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
-                    opts.inPreferQualityOverSpeed = true;
 
-                    float scale = (float) mPreviewSize / Math.max(width, height);
-                    opts.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
-                    opts.inJustDecodeBounds = false;
-                    opts.inMutable = true;
+                BitmapFactory.Options opts = new BitmapFactory.Options();
+                opts.inPreferredConfig = Bitmap.Config.ARGB_8888;
+                opts.inPreferQualityOverSpeed = true;
 
-                    if (bitmapProvider != null) {
-                        int expectedPixles = (width / opts.inSampleSize) * (height / opts.inSampleSize);
-                        Bitmap reusableBitmap = bitmapProvider.forPixelCount(expectedPixles);
-                        if (reusableBitmap != null) {
-                            // Try loading with reusable bitmap
-                            opts.inBitmap = reusableBitmap;
-                            try {
-                                mPreview = loadPreviewBitmap(opts);
-                            } catch (IllegalArgumentException e) {
-                                Log.d(TAG, "Unable to reusage bitmap", e);
-                                opts.inBitmap = null;
-                                mPreview = null;
-                            }
+                float scale = (float) MAX_PREVIEW_SIZE / Math.max(width, height);
+                opts.inSampleSize = BitmapUtils.computeSampleSizeLarger(scale);
+                opts.inJustDecodeBounds = false;
+                opts.inMutable = true;
+
+                if (bitmapProvider != null) {
+                    int expectedPixles = (width / opts.inSampleSize) * (height / opts.inSampleSize);
+                    Bitmap reusableBitmap = bitmapProvider.forPixelCount(expectedPixles);
+                    if (reusableBitmap != null) {
+                        // Try loading with reusable bitmap
+                        opts.inBitmap = reusableBitmap;
+                        try {
+                            mPreview = loadPreviewBitmap(opts);
+                        } catch (IllegalArgumentException e) {
+                            Log.d(TAG, "Unable to reusage bitmap", e);
+                            opts.inBitmap = null;
+                            mPreview = null;
                         }
                     }
-                    if (mPreview == null) {
-                        mPreview = loadPreviewBitmap(opts);
-                    }
                 }
-                mState = State.LOADED;
+                if (mPreview == null) {
+                    mPreview = loadPreviewBitmap(opts);
+                }
+
+                // Verify that the bitmap can be used on GL surface
+                try {
+                    GLUtils.getInternalFormat(mPreview);
+                    GLUtils.getType(mPreview);
+                    mState = State.LOADED;
+                } catch (IllegalArgumentException e) {
+                    Log.d(TAG, "Image cannot be rendered on a GL surface", e);
+                    mState = State.ERROR_LOADING;
+                }
                 return true;
             }
         }
@@ -237,8 +243,7 @@
 
     public static class FilePathBitmapSource extends BitmapSource {
         private String mPath;
-        public FilePathBitmapSource(String path, int previewSize) {
-            super(previewSize);
+        public FilePathBitmapSource(String path) {
             mPath = path;
         }
         @Override
@@ -272,8 +277,7 @@
     public static class UriBitmapSource extends BitmapSource {
         private Context mContext;
         private Uri mUri;
-        public UriBitmapSource(Context context, Uri uri, int previewSize) {
-            super(previewSize);
+        public UriBitmapSource(Context context, Uri uri) {
             mContext = context;
             mUri = uri;
         }
@@ -337,8 +341,7 @@
     public static class ResourceBitmapSource extends BitmapSource {
         private Resources mRes;
         private int mResId;
-        public ResourceBitmapSource(Resources res, int resId, int previewSize) {
-            super(previewSize);
+        public ResourceBitmapSource(Resources res, int resId) {
             mRes = res;
             mResId = resId;
         }
diff --git a/src/com/android/launcher3/AppsContainerRecyclerView.java b/src/com/android/launcher3/AppsContainerRecyclerView.java
index 5b1da4b..31942b3 100644
--- a/src/com/android/launcher3/AppsContainerRecyclerView.java
+++ b/src/com/android/launcher3/AppsContainerRecyclerView.java
@@ -122,30 +122,20 @@
         mApps = apps;
     }
 
-    @Override
-    public void setAdapter(Adapter adapter) {
-        // Register a change listener to update the scroll position state whenever the data set
-        // changes.
-        adapter.registerAdapterDataObserver(new AdapterDataObserver() {
-            @Override
-            public void onChanged() {
-                post(new Runnable() {
-                    @Override
-                    public void run() {
-                        refreshCurScrollPosition();
-                    }
-                });
-            }
-        });
-        super.setAdapter(adapter);
-    }
-
     /**
      * Sets the number of apps per row in this recycler view.
      */
     public void setNumAppsPerRow(int numAppsPerRow, int numPredictedAppsPerRow) {
         mNumAppsPerRow = numAppsPerRow;
         mNumPredictedAppsPerRow = numPredictedAppsPerRow;
+
+        DeviceProfile grid = LauncherAppState.getInstance().getDynamicGrid().getDeviceProfile();
+        RecyclerView.RecycledViewPool pool = getRecycledViewPool();
+        int approxRows = (int) Math.ceil(grid.availableHeightPx / grid.allAppsIconSizePx);
+        pool.setMaxRecycledViews(AppsGridAdapter.PREDICTION_BAR_SPACER_TYPE, 1);
+        pool.setMaxRecycledViews(AppsGridAdapter.EMPTY_VIEW_TYPE, 1);
+        pool.setMaxRecycledViews(AppsGridAdapter.ICON_VIEW_TYPE, approxRows * mNumAppsPerRow);
+        pool.setMaxRecycledViews(AppsGridAdapter.SECTION_BREAK_VIEW_TYPE, approxRows);
     }
 
     public void updateBackgroundPadding(Drawable background) {
@@ -186,7 +176,20 @@
      */
     public void scrollToTop() {
         scrollToPosition(0);
-        updateScrollY(0);
+    }
+
+    /**
+     * Returns the current scroll position.
+     */
+    public int getScrollPosition() {
+        List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
+        getCurScrollState(mScrollPosState, items);
+        if (mScrollPosState.rowIndex != -1) {
+            int predictionBarHeight = mApps.getPredictedApps().isEmpty() ? 0 : mPredictionBarHeight;
+            return getPaddingTop() + (mScrollPosState.rowIndex * mScrollPosState.rowHeight) +
+                    predictionBarHeight - mScrollPosState.rowTopOffset;
+        }
+        return 0;
     }
 
     @Override
@@ -357,7 +360,6 @@
             if (touchFraction <= predictionBarFraction) {
                 // Scroll to the top of the view, where the prediction bar is
                 layoutManager.scrollToPositionWithOffset(0, 0);
-                updateScrollY(0);
                 return "";
             }
         }
@@ -376,9 +378,6 @@
             lastScrollSection = scrollSection;
         }
 
-        // We need to workaround the RecyclerView to get the right scroll position
-        refreshCurScrollPosition();
-
         // Scroll to the view at the position, anchored at the top of the screen. We call the scroll
         // method on the LayoutManager directly since it is not exposed by RecyclerView.
         layoutManager.scrollToPositionWithOffset(lastScrollSection.appItem.position, 0);
@@ -402,7 +401,6 @@
         int x;
         int y;
         int predictionBarHeight = mApps.getPredictedApps().isEmpty() ? 0 : mPredictionBarHeight;
-        boolean isRtl = Utilities.isRtl(getResources());
         int rowCount = getNumRows();
         getCurScrollState(mScrollPosState, items);
         if (mScrollPosState.rowIndex != -1) {
@@ -413,7 +411,7 @@
                         (int) (height / ((float) totalScrollHeight / height)));
 
                 // Calculate the position and size of the scroll bar
-                if (isRtl) {
+                if (Utilities.isRtl(getResources())) {
                     x = mBackgroundPadding.left;
                 } else {
                     x = getWidth() - mBackgroundPadding.right - mScrollbarWidth;
@@ -442,11 +440,10 @@
         if (mFastScrollAlpha > 0f && !mFastScrollSectionName.isEmpty()) {
             int x;
             int y;
-            boolean isRtl = Utilities.isRtl(getResources());
 
             // Calculate the position for the fast scroller popup
             Rect bgBounds = mFastScrollerBg.getBounds();
-            if (isRtl) {
+            if (Utilities.isRtl(getResources())) {
                 x = mBackgroundPadding.left + getScrollBarSize();
             } else {
                 x = getWidth() - getPaddingRight() - getScrollBarSize() - bgBounds.width();
@@ -492,20 +489,6 @@
     }
 
     /**
-     * Forces a refresh of the scroll position to any scroll listener.
-     */
-    private void refreshCurScrollPosition() {
-        List<AlphabeticalAppsList.AdapterItem> items = mApps.getAdapterItems();
-        getCurScrollState(mScrollPosState, items);
-        if (mScrollPosState.rowIndex != -1) {
-            int predictionBarHeight = mApps.getPredictedApps().isEmpty() ? 0 : mPredictionBarHeight;
-            int scrollY = getPaddingTop() + (mScrollPosState.rowIndex * mScrollPosState.rowHeight) +
-                    predictionBarHeight - mScrollPosState.rowTopOffset;
-            updateScrollY(scrollY);
-        }
-    }
-
-    /**
      * Returns the current scroll state.
      */
     private void getCurScrollState(ScrollPositionState stateOut,
diff --git a/src/com/android/launcher3/AppsContainerView.java b/src/com/android/launcher3/AppsContainerView.java
index 8709101..5ccb6c6 100644
--- a/src/com/android/launcher3/AppsContainerView.java
+++ b/src/com/android/launcher3/AppsContainerView.java
@@ -35,6 +35,7 @@
 import android.view.View;
 import android.view.ViewConfiguration;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
 import android.view.inputmethod.EditorInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.FrameLayout;
@@ -47,12 +48,97 @@
 
 
 /**
+ * Interface for controlling the header elevation in response to RecyclerView scroll.
+ */
+interface HeaderElevationController {
+    void onScroll(int scrollY);
+    void disable();
+}
+
+/**
+ * Implementation of the header elevation mechanism for pre-L devices.  It simulates elevation
+ * by drawing a gradient under the header bar.
+ */
+final class HeaderElevationControllerV16 implements HeaderElevationController {
+
+    private final View mShadow;
+
+    private final float mScrollToElevation;
+
+    public HeaderElevationControllerV16(View header) {
+        Resources res = header.getContext().getResources();
+        mScrollToElevation = res.getDimension(R.dimen.all_apps_header_scroll_to_elevation);
+
+        mShadow = new View(header.getContext());
+        mShadow.setBackground(new GradientDrawable(
+                GradientDrawable.Orientation.TOP_BOTTOM, new int[] {0x44000000, 0x00000000}));
+        mShadow.setAlpha(0);
+
+        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
+                FrameLayout.LayoutParams.MATCH_PARENT,
+                res.getDimensionPixelSize(R.dimen.all_apps_header_shadow_height));
+        lp.topMargin = ((FrameLayout.LayoutParams) header.getLayoutParams()).height;
+
+        ((ViewGroup) header.getParent()).addView(mShadow, lp);
+    }
+
+    @Override
+    public void onScroll(int scrollY) {
+        float elevationPct = (float) Math.min(scrollY, mScrollToElevation) /
+                mScrollToElevation;
+        mShadow.setAlpha(elevationPct);
+    }
+
+    @Override
+    public void disable() {
+        ViewGroup parent = (ViewGroup) mShadow.getParent();
+        if (parent != null) {
+            parent.removeView(mShadow);
+        }
+    }
+}
+
+/**
+ * Implementation of the header elevation mechanism for L+ devices, which makes use of the native
+ * view elevation.
+ */
+@TargetApi(Build.VERSION_CODES.LOLLIPOP)
+final class HeaderElevationControllerVL implements HeaderElevationController {
+
+    private final View mHeader;
+    private final float mMaxElevation;
+    private final float mScrollToElevation;
+
+    public HeaderElevationControllerVL(View header) {
+        mHeader = header;
+
+        Resources res = header.getContext().getResources();
+        mMaxElevation = res.getDimension(R.dimen.all_apps_header_max_elevation);
+        mScrollToElevation = res.getDimension(R.dimen.all_apps_header_scroll_to_elevation);
+    }
+
+    @Override
+    public void onScroll(int scrollY) {
+        float elevationPct = (float) Math.min(scrollY, mScrollToElevation) /
+                mScrollToElevation;
+        float newElevation = mMaxElevation * elevationPct;
+        if (Float.compare(mHeader.getElevation(), newElevation) != 0) {
+            mHeader.setElevation(newElevation);
+        }
+    }
+
+    @Override
+    public void disable() { }
+}
+
+/**
  * The all apps view container.
  */
 public class AppsContainerView extends BaseContainerView implements DragSource, Insettable,
         TextWatcher, TextView.OnEditorActionListener, LauncherTransitionable,
         AlphabeticalAppsList.FilterChangedCallback, AppsGridAdapter.PredictionBarSpacerCallbacks,
-        View.OnTouchListener, View.OnClickListener, View.OnLongClickListener {
+        View.OnTouchListener, View.OnClickListener, View.OnLongClickListener,
+        ViewTreeObserver.OnPreDrawListener {
 
     public static final boolean GRID_MERGE_SECTIONS = true;
 
@@ -96,8 +182,7 @@
     // Normal container insets
     private int mContainerInset;
     private int mPredictionBarHeight;
-    // RecyclerView scroll position
-    @Thunk int mRecyclerViewScrollY;
+    private int mLastRecyclerViewScrollPos = -1;
 
     private CheckLongPressHelper mPredictionIconCheckForLongPress;
     private View mPredictionIconUnderTouch;
@@ -266,14 +351,6 @@
         mAppsRecyclerView.setLayoutManager(mLayoutManager);
         mAppsRecyclerView.setAdapter(mAdapter);
         mAppsRecyclerView.setHasFixedSize(true);
-        mAppsRecyclerView.setOnScrollListenerProxy(
-                new BaseContainerRecyclerView.OnScrollToListener() {
-                    @Override
-                    public void onScrolledTo(int x, int y) {
-                        mRecyclerViewScrollY = y;
-                        onRecyclerViewScrolled();
-                    }
-                });
         if (mItemDecoration != null) {
             mAppsRecyclerView.addItemDecoration(mItemDecoration);
         }
@@ -283,9 +360,7 @@
 
     @Override
     public void onBindPredictionBar() {
-        if (!updatePredictionBarVisibility()) {
-            return;
-        }
+        updatePredictionBarVisibility();
 
         List<AppInfo> predictedApps = mApps.getPredictedApps();
         int childCount = mPredictionBarView.getChildCount();
@@ -401,6 +476,12 @@
     }
 
     @Override
+    public boolean onPreDraw() {
+        synchronizeToRecyclerViewScrollPosition(mAppsRecyclerView.getScrollPosition());
+        return true;
+    }
+
+    @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
         return handleTouchEvent(ev);
     }
@@ -600,7 +681,11 @@
 
     @Override
     public void onLauncherTransitionPrepare(Launcher l, boolean animated, boolean toWorkspace) {
-        // Do nothing
+        // Register for a pre-draw listener to synchronize the recycler view scroll to other views
+        // in this container
+        if (!toWorkspace) {
+            getViewTreeObserver().addOnPreDrawListener(this);
+        }
     }
 
     @Override
@@ -620,18 +705,26 @@
                 hideSearchField(false, false);
             }
         }
+        if (toWorkspace) {
+            getViewTreeObserver().removeOnPreDrawListener(this);
+            mLastRecyclerViewScrollPos = -1;
+        }
     }
 
     /**
      * Updates the container when the recycler view is scrolled.
      */
     @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    private void onRecyclerViewScrolled() {
-        if (DYNAMIC_HEADER_ELEVATION) {
-            mElevationController.onScroll(mRecyclerViewScrollY);
-        }
+    private void synchronizeToRecyclerViewScrollPosition(int scrollY) {
+        if (mLastRecyclerViewScrollPos != scrollY) {
+            mLastRecyclerViewScrollPos = scrollY;
+            if (DYNAMIC_HEADER_ELEVATION) {
+                mElevationController.onScroll(scrollY);
+            }
 
-        mPredictionBarView.setTranslationY(-mRecyclerViewScrollY + mAppsRecyclerView.getPaddingTop());
+            // Scroll the prediction bar with the contents of the recycler view
+            mPredictionBarView.setTranslationY(-scrollY + mAppsRecyclerView.getPaddingTop());
+        }
     }
 
     @Override
@@ -686,6 +779,19 @@
                     }
                 }
                 break;
+            case MotionEvent.ACTION_MOVE:
+                if (mPredictionIconUnderTouch != null) {
+                    float dist = (float) Math.hypot(x - mPredictionIconTouchDownPos.x,
+                            y - mPredictionIconTouchDownPos.y);
+                    if (dist > ViewConfiguration.get(getContext()).getScaledTouchSlop()) {
+                        if (mPredictionIconCheckForLongPress != null) {
+                            mPredictionIconCheckForLongPress.cancelLongPress();
+                        }
+                        mPredictionIconCheckForLongPress = null;
+                        mPredictionIconUnderTouch = null;
+                    }
+                }
+                break;
             case MotionEvent.ACTION_UP:
                 if (mBoundsCheckLastTouchDownPos.x > -1) {
                     ViewConfiguration viewConfig = ViewConfiguration.get(getContext());
@@ -728,8 +834,19 @@
      * Returns the predicted app in the prediction bar given a set of local coordinates.
      */
     private View findPredictedAppAtCoordinate(int x, int y) {
-        int[] coord = {x, y};
         Rect hitRect = new Rect();
+
+        // Ensure we aren't hitting the search bar
+        int[] coord = {x, y};
+        Utilities.mapCoordInSelfToDescendent(mHeaderView, this, coord);
+        mHeaderView.getHitRect(hitRect);
+        if (hitRect.contains(coord[0], coord[1])) {
+            return null;
+        }
+
+        // Check against the children of the prediction bar
+        coord[0] = x;
+        coord[1] = y;
         Utilities.mapCoordInSelfToDescendent(mPredictionBarView, this, coord);
         for (int i = 0; i < mPredictionBarView.getChildCount(); i++) {
             View child = mPredictionBarView.getChildAt(i);
@@ -843,79 +960,4 @@
     private InputMethodManager getInputMethodManager() {
         return (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
     }
-
-    private static interface HeaderElevationController {
-
-        public void onScroll(int scrollY);
-
-        public void disable();
-    }
-
-    private static final class HeaderElevationControllerV16 implements HeaderElevationController {
-
-        private final View mShadow;
-
-        private final float mScrollToElevation;
-
-        public HeaderElevationControllerV16(View header) {
-            Resources res = header.getContext().getResources();
-            mScrollToElevation = res.getDimension(R.dimen.all_apps_header_scroll_to_elevation);
-
-            mShadow = new View(header.getContext());
-            mShadow.setBackground(new GradientDrawable(
-                    GradientDrawable.Orientation.TOP_BOTTOM, new int[] {0x44000000, 0x00000000}));
-            mShadow.setAlpha(0);
-
-            FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(
-                    LayoutParams.MATCH_PARENT,
-                    res.getDimensionPixelSize(R.dimen.all_apps_header_shadow_height));
-            lp.topMargin = ((FrameLayout.LayoutParams) header.getLayoutParams()).height;
-
-            ((ViewGroup) header.getParent()).addView(mShadow, lp);
-        }
-
-        @Override
-        public void onScroll(int scrollY) {
-            float elevationPct = (float) Math.min(scrollY, mScrollToElevation) /
-                    mScrollToElevation;
-            mShadow.setAlpha(elevationPct);
-        }
-
-        @Override
-        public void disable() {
-            ViewGroup parent = (ViewGroup) mShadow.getParent();
-            if (parent != null) {
-                parent.removeView(mShadow);
-            }
-        }
-    }
-
-    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
-    private static final class HeaderElevationControllerVL implements HeaderElevationController {
-
-        private final View mHeader;
-        private final float mMaxElevation;
-        private final float mScrollToElevation;
-
-        public HeaderElevationControllerVL(View header) {
-            mHeader = header;
-
-            Resources res = header.getContext().getResources();
-            mMaxElevation = res.getDimension(R.dimen.all_apps_header_max_elevation);
-            mScrollToElevation = res.getDimension(R.dimen.all_apps_header_scroll_to_elevation);
-        }
-
-        @Override
-        public void onScroll(int scrollY) {
-            float elevationPct = (float) Math.min(scrollY, mScrollToElevation) /
-                    mScrollToElevation;
-            float newElevation = mMaxElevation * elevationPct;
-            if (Float.compare(mHeader.getElevation(), newElevation) != 0) {
-                mHeader.setElevation(newElevation);
-            }
-        }
-
-        @Override
-        public void disable() { }
-    }
 }
diff --git a/src/com/android/launcher3/BaseContainerRecyclerView.java b/src/com/android/launcher3/BaseContainerRecyclerView.java
index 59e20ca..e52d887 100644
--- a/src/com/android/launcher3/BaseContainerRecyclerView.java
+++ b/src/com/android/launcher3/BaseContainerRecyclerView.java
@@ -29,20 +29,11 @@
 public class BaseContainerRecyclerView extends RecyclerView
         implements RecyclerView.OnItemTouchListener {
 
-    /**
-     * Listener to get notified when the absolute scroll changes.
-     */
-    public interface OnScrollToListener {
-        void onScrolledTo(int x, int y);
-    }
-
     private static final int SCROLL_DELTA_THRESHOLD_DP = 4;
 
     /** Keeps the last known scrolling delta/velocity along y-axis. */
     @Thunk int mDy = 0;
-    @Thunk int mScrollY;
     private float mDeltaThreshold;
-    private OnScrollToListener mScrollToListener;
 
     public BaseContainerRecyclerView(Context context) {
         this(context, null);
@@ -68,20 +59,9 @@
         @Override
         public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
             mDy = dy;
-            mScrollY += dy;
-            if (mScrollToListener != null) {
-                mScrollToListener.onScrolledTo(0, mScrollY);
-            }
         }
     }
 
-    /**
-     * Sets an additional scroll listener, only needed for LMR1 version of the support lib.
-     */
-    public void setOnScrollListenerProxy(OnScrollToListener listener) {
-        mScrollToListener = listener;
-    }
-
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
@@ -106,17 +86,6 @@
     }
 
     /**
-     * Updates the scroll position, used to workaround a RecyclerView issue with scrolling to
-     * position.
-     */
-    protected void updateScrollY(int scrollY) {
-        mScrollY = scrollY;
-        if (mScrollToListener != null) {
-            mScrollToListener.onScrolledTo(0, mScrollY);
-        }
-    }
-
-    /**
      * Returns whether this {@link MotionEvent} should trigger the scroll to be stopped.
      */
     protected boolean shouldStopScroll(MotionEvent ev) {