Merge "Fix for clipped promise icon." into ub-launcher3-dorval-polish
diff --git a/build.gradle b/build.gradle
index ef782d9..c23a299 100644
--- a/build.gradle
+++ b/build.gradle
@@ -68,6 +68,7 @@
 final String SUPPORT_LIBS_VERSION = '26.0.0-SNAPSHOT'
 dependencies {
     compile "com.android.support:support-v4:${SUPPORT_LIBS_VERSION}"
+    compile "com.android.support:support-dynamic-animation:${SUPPORT_LIBS_VERSION}"
     compile "com.android.support:recyclerview-v7:${SUPPORT_LIBS_VERSION}"
     compile "com.android.support:palette-v7:${SUPPORT_LIBS_VERSION}"
     compile 'com.google.protobuf.nano:protobuf-javanano:3.0.0-alpha-2'
diff --git a/res/layout/widgets_list_row_view.xml b/res/layout/widgets_list_row_view.xml
index b6e0a0b..1062269 100644
--- a/res/layout/widgets_list_row_view.xml
+++ b/res/layout/widgets_list_row_view.xml
@@ -41,6 +41,7 @@
         android:singleLine="true"
         android:textColor="?android:attr/textColorPrimary"
         android:textSize="16sp"
+        android:textAlignment="viewStart"
         launcher:customShadows="false"
         launcher:deferShadowGeneration="true"
         launcher:iconDisplay="widget_section"
diff --git a/src/com/android/launcher3/CellLayout.java b/src/com/android/launcher3/CellLayout.java
index c2c5c27..d0d33a0 100644
--- a/src/com/android/launcher3/CellLayout.java
+++ b/src/com/android/launcher3/CellLayout.java
@@ -35,6 +35,7 @@
 import android.os.Parcelable;
 import android.support.annotation.IntDef;
 import android.support.v4.view.ViewCompat;
+import android.util.ArrayMap;
 import android.util.AttributeSet;
 import android.util.Log;
 import android.util.SparseArray;
@@ -44,7 +45,6 @@
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.DecelerateInterpolator;
-
 import com.android.launcher3.BubbleTextView.BubbleTextShadowHandler;
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.accessibility.DragAndDropAccessibilityDelegate;
@@ -59,14 +59,12 @@
 import com.android.launcher3.util.ParcelableSparseArray;
 import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.Thunk;
-
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashMap;
 import java.util.Stack;
 
 public class CellLayout extends ViewGroup implements BubbleTextShadowHandler {
@@ -76,7 +74,7 @@
     private static final String TAG = "CellLayout";
     private static final boolean LOGD = false;
 
-    private Launcher mLauncher;
+    private final Launcher mLauncher;
     @ViewDebug.ExportedProperty(category = "launcher")
     @Thunk int mCellWidth;
     @ViewDebug.ExportedProperty(category = "launcher")
@@ -102,10 +100,10 @@
     private GridOccupancy mTmpOccupied;
 
     private OnTouchListener mInterceptTouchListener;
-    private StylusEventHelper mStylusEventHelper;
+    private final StylusEventHelper mStylusEventHelper;
 
-    private ArrayList<FolderIcon.PreviewBackground> mFolderBackgrounds = new ArrayList<FolderIcon.PreviewBackground>();
-    FolderIcon.PreviewBackground mFolderLeaveBehind = new FolderIcon.PreviewBackground();
+    private final ArrayList<FolderIcon.PreviewBackground> mFolderBackgrounds = new ArrayList<>();
+    final FolderIcon.PreviewBackground mFolderLeaveBehind = new FolderIcon.PreviewBackground();
 
     private float mBackgroundAlpha;
 
@@ -122,9 +120,9 @@
 
     // These arrays are used to implement the drag visualization on x-large screens.
     // They are used as circular arrays, indexed by mDragOutlineCurrent.
-    @Thunk Rect[] mDragOutlines = new Rect[4];
-    @Thunk float[] mDragOutlineAlphas = new float[mDragOutlines.length];
-    private InterruptibleInOutAnimator[] mDragOutlineAnims =
+    @Thunk final Rect[] mDragOutlines = new Rect[4];
+    @Thunk final float[] mDragOutlineAlphas = new float[mDragOutlines.length];
+    private final InterruptibleInOutAnimator[] mDragOutlineAnims =
             new InterruptibleInOutAnimator[mDragOutlines.length];
 
     // Used as an index into the above 3 arrays; indicates which is the most current value.
@@ -133,8 +131,8 @@
 
     private final ClickShadowView mTouchFeedbackView;
 
-    @Thunk HashMap<CellLayout.LayoutParams, Animator> mReorderAnimators = new HashMap<>();
-    @Thunk HashMap<View, ReorderPreviewAnimation> mShakeAnimators = new HashMap<>();
+    @Thunk final ArrayMap<LayoutParams, Animator> mReorderAnimators = new ArrayMap<>();
+    @Thunk final ArrayMap<View, ReorderPreviewAnimation> mShakeAnimators = new ArrayMap<>();
 
     private boolean mItemPlacementDirty = false;
 
@@ -143,8 +141,8 @@
 
     private boolean mDragging = false;
 
-    private TimeInterpolator mEaseOutInterpolator;
-    private ShortcutAndWidgetContainer mShortcutsAndWidgets;
+    private final TimeInterpolator mEaseOutInterpolator;
+    private final ShortcutAndWidgetContainer mShortcutsAndWidgets;
 
     @Retention(RetentionPolicy.SOURCE)
     @IntDef({WORKSPACE, HOTSEAT, FOLDER})
@@ -169,10 +167,10 @@
     private static final int REORDER_ANIMATION_DURATION = 150;
     @Thunk final float mReorderPreviewAnimationMagnitude;
 
-    private ArrayList<View> mIntersectingViews = new ArrayList<View>();
-    private Rect mOccupiedRect = new Rect();
-    private int[] mDirectionVector = new int[2];
-    int[] mPreviousReorderDirection = new int[2];
+    private final ArrayList<View> mIntersectingViews = new ArrayList<>();
+    private final Rect mOccupiedRect = new Rect();
+    private final int[] mDirectionVector = new int[2];
+    final int[] mPreviousReorderDirection = new int[2];
     private static final int INVALID_DIRECTION = -100;
 
     private final Rect mTempRect = new Rect();
@@ -1100,7 +1098,7 @@
                 result, resultSpan);
     }
 
-    private final Stack<Rect> mTempRectStack = new Stack<Rect>();
+    private final Stack<Rect> mTempRectStack = new Stack<>();
     private void lazyInitTempRectStack() {
         if (mTempRectStack.isEmpty()) {
             for (int i = 0; i < mCountX * mCountY; i++) {
@@ -1145,7 +1143,7 @@
         final int[] bestXY = result != null ? result : new int[2];
         double bestDistance = Double.MAX_VALUE;
         final Rect bestRect = new Rect(-1, -1, -1, -1);
-        final Stack<Rect> validRegions = new Stack<Rect>();
+        final Stack<Rect> validRegions = new Stack<>();
 
         final int countX = mCountX;
         final int countY = mCountY;
@@ -1347,14 +1345,14 @@
         final static int RIGHT = 1 << 2;
         final static int BOTTOM = 1 << 3;
 
-        ArrayList<View> views;
-        ItemConfiguration config;
-        Rect boundingRect = new Rect();
+        final ArrayList<View> views;
+        final ItemConfiguration config;
+        final Rect boundingRect = new Rect();
 
-        int[] leftEdge = new int[mCountY];
-        int[] rightEdge = new int[mCountY];
-        int[] topEdge = new int[mCountX];
-        int[] bottomEdge = new int[mCountX];
+        final int[] leftEdge = new int[mCountY];
+        final int[] rightEdge = new int[mCountY];
+        final int[] topEdge = new int[mCountX];
+        final int[] bottomEdge = new int[mCountX];
         int dirtyEdges;
         boolean boundingRectDirty;
 
@@ -1494,7 +1492,7 @@
             return boundingRect;
         }
 
-        PositionComparator comparator = new PositionComparator();
+        final PositionComparator comparator = new PositionComparator();
         class PositionComparator implements Comparator<View> {
             int whichEdge = 0;
             public int compare(View left, View right) {
@@ -1794,7 +1792,7 @@
             }
         }
 
-        solution.intersectingViews = new ArrayList<View>(mIntersectingViews);
+        solution.intersectingViews = new ArrayList<>(mIntersectingViews);
 
         // First we try to find a solution which respects the push mechanic. That is,
         // we try to find a solution such that no displaced item travels through another item
@@ -1850,7 +1848,7 @@
         int result[] = new int[2];
         result = findNearestArea(pixelX, pixelY, spanX, spanY, result);
 
-        boolean success = false;
+        boolean success;
         // First we try the exact nearest position of the item being dragged,
         // we will then want to try to move this around to other neighbouring positions
         success = rearrangementExists(result[0], result[1], spanX, spanY, direction, dragView,
@@ -1958,14 +1956,14 @@
     // Class which represents the reorder preview animations. These animations show that an item is
     // in a temporary state, and hint at where the item will return to.
     class ReorderPreviewAnimation {
-        View child;
+        final View child;
         float finalDeltaX;
         float finalDeltaY;
         float initDeltaX;
         float initDeltaY;
-        float finalScale;
+        final float finalScale;
         float initScale;
-        int mode;
+        final int mode;
         boolean repeating = false;
         private static final int PREVIEW_DURATION = 300;
         private static final int HINT_DURATION = Workspace.REORDER_TIMEOUT;
@@ -2415,9 +2413,9 @@
     }
 
     private static class ItemConfiguration extends CellAndSpan {
-        HashMap<View, CellAndSpan> map = new HashMap<View, CellAndSpan>();
-        private HashMap<View, CellAndSpan> savedMap = new HashMap<View, CellAndSpan>();
-        ArrayList<View> sortedViews = new ArrayList<View>();
+        final ArrayMap<View, CellAndSpan> map = new ArrayMap<>();
+        private final ArrayMap<View, CellAndSpan> savedMap = new ArrayMap<>();
+        final ArrayList<View> sortedViews = new ArrayList<>();
         ArrayList<View> intersectingViews;
         boolean isSolution = false;
 
@@ -2467,7 +2465,6 @@
      * @param pixelY The Y location at which you want to search for a vacant area.
      * @param spanX Horizontal span of the object.
      * @param spanY Vertical span of the object.
-     * @param ignoreView Considers space occupied by this view as unoccupied
      * @param result Previously returned value to possibly recycle.
      * @return The X, Y cell of a vacant area that can contain this object,
      *         nearest the requested location.
@@ -2779,9 +2776,9 @@
     //    cellX and cellY coordinates and which page was clicked. We then set this as a tag on
     //    the CellLayout that was long clicked
     public static final class CellInfo extends CellAndSpan {
-        public View cell;
-        long screenId;
-        long container;
+        public final View cell;
+        final long screenId;
+        final long container;
 
         public CellInfo(View v, ItemInfo info) {
             cellX = info.cellX;
diff --git a/src/com/android/launcher3/compat/UserManagerCompatVL.java b/src/com/android/launcher3/compat/UserManagerCompatVL.java
index c7f88f6..bb42573 100644
--- a/src/com/android/launcher3/compat/UserManagerCompatVL.java
+++ b/src/com/android/launcher3/compat/UserManagerCompatVL.java
@@ -21,13 +21,11 @@
 import android.content.pm.PackageManager;
 import android.os.UserHandle;
 import android.os.UserManager;
-
+import android.util.ArrayMap;
 import com.android.launcher3.util.LongArrayMap;
 import com.android.launcher3.util.ManagedProfileHeuristic;
-
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
 
 public class UserManagerCompatVL extends UserManagerCompat {
@@ -40,7 +38,7 @@
     protected LongArrayMap<UserHandle> mUsers;
     // Create a separate reverse map as LongArrayMap.indexOfValue checks if objects are same
     // and not {@link Object#equals}
-    protected HashMap<UserHandle, Long> mUserToSerialMap;
+    protected ArrayMap<UserHandle, Long> mUserToSerialMap;
 
     UserManagerCompatVL(Context context) {
         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
@@ -88,7 +86,7 @@
     public void enableAndResetCache() {
         synchronized (this) {
             mUsers = new LongArrayMap<>();
-            mUserToSerialMap = new HashMap<>();
+            mUserToSerialMap = new ArrayMap<>();
             List<UserHandle> users = mUserManager.getUserProfiles();
             if (users != null) {
                 for (UserHandle user : users) {
diff --git a/src/com/android/launcher3/graphics/DrawableFactory.java b/src/com/android/launcher3/graphics/DrawableFactory.java
index 60bbce4..45344c0 100644
--- a/src/com/android/launcher3/graphics/DrawableFactory.java
+++ b/src/com/android/launcher3/graphics/DrawableFactory.java
@@ -28,16 +28,14 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.support.annotation.UiThread;
+import android.util.ArrayMap;
 import android.util.Log;
-
 import com.android.launcher3.FastBitmapDrawable;
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.allapps.AllAppsBackgroundDrawable;
 
-import java.util.HashMap;
-
 /**
  * Factory for creating new drawables.
  */
@@ -61,7 +59,7 @@
     }
 
     protected final UserHandle mMyUser = Process.myUserHandle();
-    protected final HashMap<UserHandle, Bitmap> mUserBadges = new HashMap<>();
+    protected final ArrayMap<UserHandle, Bitmap> mUserBadges = new ArrayMap<>();
 
     /**
      * Returns a FastBitmapDrawable with the icon.
diff --git a/src/com/android/launcher3/model/BgDataModel.java b/src/com/android/launcher3/model/BgDataModel.java
index d9c5143..816c1d4 100644
--- a/src/com/android/launcher3/model/BgDataModel.java
+++ b/src/com/android/launcher3/model/BgDataModel.java
@@ -152,7 +152,7 @@
             for (ArrayList<String> map : deepShortcutMap.values()) {
                 writer.print(prefix + "  ");
                 for (String str : map) {
-                    writer.print(str.toString() + ", ");
+                    writer.print(str + ", ");
                 }
                 writer.println();
             }
@@ -166,7 +166,7 @@
         DumpTargetWrapper hotseat = new DumpTargetWrapper(ContainerType.HOTSEAT, 0);
         LongArrayMap<DumpTargetWrapper> workspaces = new LongArrayMap<>();
         for (int i = 0; i < workspaceScreens.size(); i++) {
-            workspaces.put(new Long(workspaceScreens.get(i)),
+            workspaces.put(workspaceScreens.get(i),
                     new DumpTargetWrapper(ContainerType.WORKSPACE, i));
         }
         DumpTargetWrapper dtw;
@@ -183,7 +183,7 @@
             if (fInfo.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
                 hotseat.add(dtw);
             } else if (fInfo.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
-                workspaces.get(new Long(fInfo.screenId)).add(dtw);
+                workspaces.get(fInfo.screenId).add(dtw);
             }
         }
         // Add leaf nodes (L3): *Info
@@ -197,7 +197,7 @@
             if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
                 hotseat.add(dtw);
             } else if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
-                workspaces.get(new Long(info.screenId)).add(dtw);
+                workspaces.get(info.screenId).add(dtw);
             }
         }
         for (int i = 0; i < appWidgets.size(); i++) {
@@ -207,7 +207,7 @@
             if (info.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT) {
                 hotseat.add(dtw);
             } else if (info.container == LauncherSettings.Favorites.CONTAINER_DESKTOP) {
-                workspaces.get(new Long(info.screenId)).add(dtw);
+                workspaces.get(info.screenId).add(dtw);
             }
         }
 
diff --git a/src/com/android/launcher3/model/GridSizeMigrationTask.java b/src/com/android/launcher3/model/GridSizeMigrationTask.java
index 221798b..8de0de0 100644
--- a/src/com/android/launcher3/model/GridSizeMigrationTask.java
+++ b/src/com/android/launcher3/model/GridSizeMigrationTask.java
@@ -13,7 +13,6 @@
 import android.net.Uri;
 import android.text.TextUtils;
 import android.util.Log;
-
 import com.android.launcher3.InvariantDeviceProfile;
 import com.android.launcher3.ItemInfo;
 import com.android.launcher3.LauncherAppState;
@@ -29,10 +28,8 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.util.GridOccupancy;
 import com.android.launcher3.util.LongArrayMap;
-
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Locale;
 
@@ -61,7 +58,6 @@
     private final Context mContext;
     private final InvariantDeviceProfile mIdp;
 
-    private final HashMap<String, Point> mWidgetMinSize = new HashMap<>();
     private final ContentValues mTempValues = new ContentValues();
     protected final ArrayList<Long> mEntryToRemove = new ArrayList<>();
     private final ArrayList<ContentProviderOperation> mUpdateOperations = new ArrayList<>();
@@ -728,8 +724,10 @@
                         int widgetId = c.getInt(indexAppWidgetId);
                         LauncherAppWidgetProviderInfo pInfo = AppWidgetManagerCompat.getInstance(
                                 mContext).getLauncherAppWidgetInfo(widgetId);
-                        Point spans = pInfo == null ?
-                                mWidgetMinSize.get(provider) : pInfo.getMinSpans(mIdp, mContext);
+                        Point spans = null;
+                        if (pInfo != null) {
+                            spans = pInfo.getMinSpans(mIdp, mContext);
+                        }
                         if (spans != null) {
                             entry.minSpanX = spans.x > 0 ? spans.x : entry.spanX;
                             entry.minSpanY = spans.y > 0 ? spans.y : entry.spanY;
@@ -865,7 +863,7 @@
     }
 
     private static ArrayList<DbEntry> deepCopy(ArrayList<DbEntry> src) {
-        ArrayList<DbEntry> dup = new ArrayList<DbEntry>(src.size());
+        ArrayList<DbEntry> dup = new ArrayList<>(src.size());
         for (DbEntry e : src) {
             dup.add(e.copy());
         }
@@ -909,7 +907,7 @@
         try {
             boolean dbChanged = false;
 
-            HashSet validPackages = getValidPackages(context);
+            HashSet<String> validPackages = getValidPackages(context);
             // Hotseat
             int srcHotseatCount = prefs.getInt(KEY_MIGRATION_SRC_HOTSEAT_COUNT, idp.numHotseatIcons);
             if (srcHotseatCount != idp.numHotseatIcons) {
@@ -962,7 +960,7 @@
         // this set is removed.
         // Since the loader removes such items anyway, removing these items here doesn't cause
         // any extra data loss and gives us more free space on the grid for better migration.
-        HashSet validPackages = new HashSet<>();
+        HashSet<String> validPackages = new HashSet<>();
         for (PackageInfo info : context.getPackageManager()
                 .getInstalledPackages(PackageManager.GET_UNINSTALLED_PACKAGES)) {
             validPackages.add(info.packageName);
diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java
index b24d682..bb2d0b6 100644
--- a/src/com/android/launcher3/model/LoaderTask.java
+++ b/src/com/android/launcher3/model/LoaderTask.java
@@ -576,7 +576,8 @@
                                     // available or not available. We do not need to track
                                     // any future restore updates.
                                     int status = c.restoreFlag &
-                                            ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED;
+                                            ~LauncherAppWidgetInfo.FLAG_RESTORE_STARTED &
+                                            ~LauncherAppWidgetInfo.FLAG_PROVIDER_NOT_READY;
                                     if (!wasProviderReady) {
                                         // If provider was not previously ready, update the
                                         // status and UI flag.
@@ -584,9 +585,6 @@
                                         // Id would be valid only if the widget restore broadcast was received.
                                         if (isIdValid) {
                                             status |= LauncherAppWidgetInfo.FLAG_UI_NOT_READY;
-                                        } else {
-                                            status &= ~LauncherAppWidgetInfo
-                                                    .FLAG_PROVIDER_NOT_READY;
                                         }
                                     }
                                     appWidgetInfo.restoreStatus = status;
diff --git a/src_flags/com/android/launcher3/config/FeatureFlags.java b/src_flags/com/android/launcher3/config/FeatureFlags.java
index ed169b6..40200c5 100644
--- a/src_flags/com/android/launcher3/config/FeatureFlags.java
+++ b/src_flags/com/android/launcher3/config/FeatureFlags.java
@@ -42,6 +42,8 @@
     public static boolean LAUNCHER3_GRADIENT_ALL_APPS = true;
     // When enabled allows use of physics based motions in the Launcher.
     public static boolean LAUNCHER3_PHYSICS = true;
+    // When enabled allows use of spring motions on the icons.
+    public static boolean LAUNCHER3_SPRING_ICONS = true;
 
     // Feature flag to enable moving the QSB on the 0th screen of the workspace.
     public static final boolean QSB_ON_FIRST_SCREEN = true;