Merge "Prevent extra animation when scrolling the recycler view." into ub-launcher3-burnaby
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 03e9bbf..873ca32 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -83,6 +83,7 @@
             android:windowSoftInputMode="adjustPan"
             android:screenOrientation="nosensor"
             android:resumeWhilePausing="true"
+            android:taskAffinity=""
             android:enabled="true">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
index d9bfc30..88dc3e2 100644
--- a/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
+++ b/WallpaperPicker/src/com/android/launcher3/WallpaperPickerActivity.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3;
 
+import android.Manifest.permission;
 import android.animation.LayoutTransition;
 import android.annotation.TargetApi;
 import android.app.ActionBar;
@@ -37,10 +38,12 @@
 import android.graphics.RectF;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.Manifest;
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.Process;
 import android.provider.MediaStore;
 import android.util.Log;
 import android.util.Pair;
@@ -680,6 +683,16 @@
     }
 
     protected Bitmap getThumbnailOfLastPhoto() {
+        boolean canReadExternalStorage = getActivity().checkPermission(
+                Manifest.permission.READ_EXTERNAL_STORAGE, Process.myPid(), Process.myUid()) ==
+                PackageManager.PERMISSION_GRANTED;
+
+        if (!canReadExternalStorage) {
+            // MediaStore.Images.Media.EXTERNAL_CONTENT_URI requires
+            // the READ_EXTERNAL_STORAGE permission
+            return null;
+        }
+
         Cursor cursor = MediaStore.Images.Media.query(getContext().getContentResolver(),
                 MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                 new String[] { MediaStore.Images.ImageColumns._ID,
diff --git a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
index 6ff2ec6..2c4184d 100644
--- a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
+++ b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java
@@ -15,7 +15,6 @@
  */
 package com.android.launcher3;
 
-import android.animation.Animator;
 import android.animation.AnimatorSet;
 import android.animation.ArgbEvaluator;
 import android.animation.ObjectAnimator;
@@ -29,6 +28,8 @@
 import android.view.MotionEvent;
 import android.view.ViewConfiguration;
 
+import com.android.launcher3.util.Thunk;
+
 /**
  * The track and scrollbar that shows when you scroll the list.
  */
@@ -41,20 +42,20 @@
     private final static int MAX_TRACK_ALPHA = 30;
     private final static int SCROLL_BAR_VIS_DURATION = 150;
 
-    private BaseRecyclerView mRv;
+    @Thunk BaseRecyclerView mRv;
     private BaseRecyclerViewFastScrollPopup mPopup;
 
     private AnimatorSet mScrollbarAnimator;
 
     private int mThumbInactiveColor;
     private int mThumbActiveColor;
-    private Point mThumbOffset = new Point(-1, -1);
-    private Paint mThumbPaint;
+    @Thunk Point mThumbOffset = new Point(-1, -1);
+    @Thunk Paint mThumbPaint;
     private Paint mTrackPaint;
     private int mThumbMinWidth;
     private int mThumbMaxWidth;
-    private int mThumbWidth;
-    private int mThumbHeight;
+    @Thunk int mThumbWidth;
+    @Thunk int mThumbHeight;
     // The inset is the buffer around which a point will still register as a click on the scrollbar
     private int mTouchInset;
     private boolean mIsDragging;
diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
index 399ef97..b8916a7 100644
--- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
+++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java
@@ -192,9 +192,6 @@
 
     @Thunk final ZoomInInterpolator mZoomInInterpolator = new ZoomInInterpolator();
 
-    // These properties refer to the background protection gradient used for AllApps and Widget tray.
-    @Thunk ValueAnimator mBackgroundFadeOutAnimation;
-
     @Thunk float mSpringLoadedShrinkFactor;
     @Thunk float mOverviewModeShrinkFactor;
     @Thunk float mWorkspaceScrimAlpha;
@@ -548,25 +545,29 @@
      * @param animated whether or not to set the background alpha immediately
      * @duration duration of the animation
      */
-    private void animateBackgroundGradient(TransitionStates states, boolean animated, int duration) {
+    private void animateBackgroundGradient(TransitionStates states,
+            boolean animated, int duration) {
+
         final DragLayer dragLayer = mLauncher.getDragLayer();
         final float startAlpha = dragLayer.getBackgroundAlpha();
         float finalAlpha = states.stateIsNormal ? 0 : mWorkspaceScrimAlpha;
 
         if (finalAlpha != startAlpha) {
             if (animated) {
-                mBackgroundFadeOutAnimation =
+                // These properties refer to the background protection gradient used for AllApps
+                // and Widget tray.
+                ValueAnimator bgFadeOutAnimation =
                         LauncherAnimUtils.ofFloat(mWorkspace, startAlpha, finalAlpha);
-                mBackgroundFadeOutAnimation.addUpdateListener(
-                        new ValueAnimator.AnimatorUpdateListener() {
+                bgFadeOutAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                    @Override
                     public void onAnimationUpdate(ValueAnimator animation) {
                         dragLayer.setBackgroundAlpha(
                                 ((Float)animation.getAnimatedValue()).floatValue());
                     }
                 });
-                mBackgroundFadeOutAnimation.setInterpolator(new DecelerateInterpolator(1.5f));
-                mBackgroundFadeOutAnimation.setDuration(duration);
-                mStateAnimator.play(mBackgroundFadeOutAnimation);
+                bgFadeOutAnimation.setInterpolator(new DecelerateInterpolator(1.5f));
+                bgFadeOutAnimation.setDuration(duration);
+                mStateAnimator.play(bgFadeOutAnimation);
             } else {
                 dragLayer.setBackgroundAlpha(finalAlpha);
             }
@@ -577,17 +578,10 @@
      * Cancels the current animation.
      */
     private void cancelAnimation() {
-        cancelAnimator(mStateAnimator);
-        mStateAnimator = null;
-    }
-
-    /**
-     * Cancels the specified animation.
-     */
-    private void cancelAnimator(Animator animator) {
-        if (animator != null) {
-            animator.setDuration(0);
-            animator.cancel();
+        if (mStateAnimator != null) {
+            mStateAnimator.setDuration(0);
+            mStateAnimator.cancel();
         }
+        mStateAnimator = null;
     }
 }
\ No newline at end of file
diff --git a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
index c83c6cf..874e895 100644
--- a/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsRecyclerView.java
@@ -23,11 +23,13 @@
 import android.util.AttributeSet;
 import android.view.ContextThemeWrapper;
 import android.view.View;
+
 import com.android.launcher3.BaseRecyclerView;
 import com.android.launcher3.BaseRecyclerViewFastScrollBar;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.Stats;
+import com.android.launcher3.util.Thunk;
 
 import java.util.List;
 
@@ -47,10 +49,11 @@
     private int mNumAppsPerRow;
     private int mPredictionBarHeight;
 
-    private BaseRecyclerViewFastScrollBar.FastScrollFocusableView mLastFastScrollFocusedView;
-    private int mPrevFastScrollFocusedPosition;
-    private int mFastScrollFrameIndex;
-    private int[] mFastScrollFrames = new int[10];
+    @Thunk BaseRecyclerViewFastScrollBar.FastScrollFocusableView mLastFastScrollFocusedView;
+    @Thunk int mPrevFastScrollFocusedPosition;
+    @Thunk int mFastScrollFrameIndex;
+    @Thunk final int[] mFastScrollFrames = new int[10];
+
     private final int mFastScrollMode = FAST_SCROLL_MODE_JUMP_TO_FIRST_ICON;
     private final int mScrollBarMode = FAST_SCROLL_BAR_MODE_DISTRIBUTE_BY_ROW;
 
@@ -267,7 +270,7 @@
      * This runnable runs a single frame of the smooth scroll animation and posts the next frame
      * if necessary.
      */
-    private Runnable mSmoothSnapNextFrameRunnable = new Runnable() {
+    @Thunk Runnable mSmoothSnapNextFrameRunnable = new Runnable() {
         @Override
         public void run() {
             if (mFastScrollFrameIndex < mFastScrollFrames.length) {