Icons are not updated to TYPE_APPLICATION during restore

> Use low res only for app shortcuts
> Running icon migration after restore
> Running icon migration again for all users
> Deduping shortcuts added from widget tray

Bug: 20945600
Change-Id: I3bb47545fdd9832510069026fbae8966d2311cc1
diff --git a/src/com/android/launcher3/InstallShortcutReceiver.java b/src/com/android/launcher3/InstallShortcutReceiver.java
index 115598f..448cc1d 100644
--- a/src/com/android/launcher3/InstallShortcutReceiver.java
+++ b/src/com/android/launcher3/InstallShortcutReceiver.java
@@ -156,6 +156,16 @@
         queuePendingShortcutInfo(info, context);
     }
 
+    public static ShortcutInfo fromShortcutIntent(Context context, Intent data) {
+        PendingInstallShortcutInfo info = new PendingInstallShortcutInfo(data, context);
+        if (info.launchIntent == null || info.label == null) {
+            if (DBG) Log.e(TAG, "Invalid install shortcut intent");
+            return null;
+        }
+        info = convertToLauncherActivityIfPossible(info);
+        return info.getShortcutInfo();
+    }
+
     static void queueInstallShortcut(LauncherActivityInfoCompat info, Context context) {
         queuePendingShortcutInfo(new PendingInstallShortcutInfo(info, context), context);
     }
@@ -215,30 +225,6 @@
     }
 
     /**
-     * Returns true if the intent is a valid launch intent for a shortcut.
-     * This is used to identify shortcuts which are different from the ones exposed by the
-     * applications' manifest file.
-     *
-     * When DISABLE_ALL_APPS is true, shortcuts exposed via the app's manifest should never be
-     * duplicated or removed(unless the app is un-installed).
-     *
-     * @param launchIntent The intent that will be launched when the shortcut is clicked.
-     */
-    static boolean isValidShortcutLaunchIntent(Intent launchIntent) {
-        if (launchIntent != null
-                && Intent.ACTION_MAIN.equals(launchIntent.getAction())
-                && launchIntent.getComponent() != null
-                && launchIntent.getCategories() != null
-                && launchIntent.getCategories().size() == 1
-                && launchIntent.hasCategory(Intent.CATEGORY_LAUNCHER)
-                && launchIntent.getExtras() == null
-                && TextUtils.isEmpty(launchIntent.getDataString())) {
-            return false;
-        }
-        return true;
-    }
-
-    /**
      * Ensures that we have a valid, non-null name.  If the provided name is null, we will return
      * the application name instead.
      */
@@ -428,7 +414,7 @@
             // Already an activity target
             return original;
         }
-        if (isValidShortcutLaunchIntent(original.launchIntent)
+        if (!Utilities.isLauncherAppTarget(original.launchIntent)
                 || !original.user.equals(UserHandleCompat.myUserHandle())) {
             // We can only convert shortcuts which point to a main activity in the current user.
             return original;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 59ca978..6697dc1 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -806,7 +806,7 @@
         }
 
         boolean isWidgetDrop = (requestCode == REQUEST_PICK_APPWIDGET ||
-                requestCode == REQUEST_CREATE_APPWIDGET || requestCode == REQUEST_CREATE_SHORTCUT);
+                requestCode == REQUEST_CREATE_APPWIDGET);
 
         final boolean workspaceLocked = isWorkspaceLocked();
         // We have special handling for widgets
@@ -1550,14 +1550,13 @@
         int[] touchXY = mPendingAddInfo.dropPos;
         CellLayout layout = getCellLayout(container, screenId);
 
-        boolean foundCellSpan = false;
-
-        ShortcutInfo info = mModel.infoFromShortcutIntent(this, data);
+        ShortcutInfo info = InstallShortcutReceiver.fromShortcutIntent(this, data);
         if (info == null) {
             return;
         }
         final View view = createShortcut(info);
 
+        boolean foundCellSpan = false;
         // First we check if we already know the exact location where we want to add this item.
         if (cellX >= 0 && cellY >= 0) {
             cellXY[0] = cellX;
diff --git a/src/com/android/launcher3/LauncherBackupAgentHelper.java b/src/com/android/launcher3/LauncherBackupAgentHelper.java
index 5f7173f..e607a0f 100644
--- a/src/com/android/launcher3/LauncherBackupAgentHelper.java
+++ b/src/com/android/launcher3/LauncherBackupAgentHelper.java
@@ -94,6 +94,7 @@
             // TODO: Update the backup set to include rank.
             if (mHelper.restoredBackupVersion <= 2) {
                 LauncherAppState.getLauncherProvider().updateFolderItemsRank();
+                LauncherAppState.getLauncherProvider().convertShortcutsToLauncherActivities();
             }
         } else {
             if (VERBOSE) Log.v(TAG, "Nothing was restored, clearing DB");
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index d994dc7..1b92602 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -2027,7 +2027,7 @@
                                                 "constructing info for partially restored package",
                                                 true);
                                         info = getRestoredItemInfo(c, titleIndex, intent,
-                                                promiseType, useLowResIcon);
+                                                promiseType);
                                         intent = getRestoredItemIntent(c, context, intent);
                                     } else {
                                         // Don't restore items for other profiles.
@@ -3402,10 +3402,10 @@
      * to a package that is not yet installed on the system.
      */
     public ShortcutInfo getRestoredItemInfo(Cursor cursor, int titleIndex, Intent intent,
-            int promiseType, boolean useLowResIcon) {
+            int promiseType) {
         final ShortcutInfo info = new ShortcutInfo();
         info.user = UserHandleCompat.myUserHandle();
-        mIconCache.getTitleAndIcon(info, intent, info.user, useLowResIcon);
+        mIconCache.getTitleAndIcon(info, intent, info.user, false /* useLowResIcon */);
 
         if ((promiseType & ShortcutInfo.FLAG_RESTORED_ICON) != 0) {
             String title = (cursor != null) ? cursor.getString(titleIndex) : null;
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 8bc8988..8fef32d 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -65,7 +65,7 @@
     private static final String TAG = "Launcher.LauncherProvider";
     private static final boolean LOGD = false;
 
-    private static final int DATABASE_VERSION = 25;
+    private static final int DATABASE_VERSION = 26;
 
     static final String OLD_AUTHORITY = "com.android.launcher2.settings";
     static final String AUTHORITY = ProviderConfig.AUTHORITY;
@@ -378,6 +378,11 @@
         mOpenHelper.updateFolderItemsRank(mOpenHelper.getWritableDatabase(), false);
     }
 
+    public void convertShortcutsToLauncherActivities() {
+        mOpenHelper.convertShortcutsToLauncherActivities(mOpenHelper.getWritableDatabase());
+    }
+
+
     public void deleteDatabase() {
         // Are you sure? (y/n)
         final SQLiteDatabase db = mOpenHelper.getWritableDatabase();
@@ -623,10 +628,12 @@
                     }
                 }
                 case 23:
-                    convertShortcutsToLauncherActivities(db);
+                    // No-op
                 case 24:
                     ManagedProfileHeuristic.markExistingUsersForNoFolderCreation(mContext);
-                case 25: {
+                case 25:
+                    convertShortcutsToLauncherActivities(db);
+                case 26: {
                     // DB Upgraded successfully
                     return;
                 }
diff --git a/src/com/android/launcher3/Utilities.java b/src/com/android/launcher3/Utilities.java
index 1f8a6f2..9f47e13 100644
--- a/src/com/android/launcher3/Utilities.java
+++ b/src/com/android/launcher3/Utilities.java
@@ -45,12 +45,15 @@
 import android.graphics.drawable.PaintDrawable;
 import android.os.Build;
 import android.os.Process;
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.Pair;
 import android.util.SparseArray;
 import android.view.View;
 import android.widget.Toast;
 
+import junit.framework.Assert;
+
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.util.ArrayList;
@@ -58,8 +61,6 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import junit.framework.Assert;
-
 /**
  * Various utilities shared amongst the Launcher's classes.
  */
@@ -650,4 +651,22 @@
             Assert.assertTrue(LauncherModel.sWorkerThread.getThreadId() == Process.myTid());
         }
     }
+
+    /**
+     * Returns true if the intent is a valid launch intent for a launcher activity of an app.
+     * This is used to identify shortcuts which are different from the ones exposed by the
+     * applications' manifest file.
+     *
+     * @param launchIntent The intent that will be launched when the shortcut is clicked.
+     */
+    public static boolean isLauncherAppTarget(Intent launchIntent) {
+        return launchIntent != null
+                && Intent.ACTION_MAIN.equals(launchIntent.getAction())
+                && launchIntent.getComponent() != null
+                && launchIntent.getCategories() != null
+                && launchIntent.getCategories().size() == 1
+                && launchIntent.hasCategory(Intent.CATEGORY_LAUNCHER)
+                && launchIntent.getExtras() == null
+                && TextUtils.isEmpty(launchIntent.getDataString());
+    }
 }