Merge "Updating screen background assets. (Bug 12136457)" into jb-ub-now-kermit
diff --git a/src/com/android/launcher3/LauncherModel.java b/src/com/android/launcher3/LauncherModel.java
index 4478e9b..2102a1f 100644
--- a/src/com/android/launcher3/LauncherModel.java
+++ b/src/com/android/launcher3/LauncherModel.java
@@ -2709,7 +2709,7 @@
         return widgetsAndShortcuts;
     }
 
-    private boolean isPackageDisabled(PackageManager pm, String packageName) {
+    private static boolean isPackageDisabled(PackageManager pm, String packageName) {
         try {
             PackageInfo pi = pm.getPackageInfo(packageName, 0);
             return !pi.applicationInfo.enabled;
@@ -2718,7 +2718,8 @@
         }
         return false;
     }
-    private boolean isValidPackageComponent(PackageManager pm, ComponentName cn) {
+
+    public static boolean isValidPackageComponent(PackageManager pm, ComponentName cn) {
         if (cn == null) {
             return false;
         }
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index 5676a9a..c797cc4 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -1474,7 +1474,6 @@
                 // Ignore
             }
 
-
             // We already have a favorites database in the old provider
             if (c != null) {
                 try {
@@ -1516,10 +1515,12 @@
                         final int width = (int) grid.numColumns;
                         final int height = (int) grid.numRows;
                         final int hotseatWidth = (int) grid.numHotseatIcons;
+                        PackageManager pm = mContext.getPackageManager();
 
                         final HashSet<String> seenIntents = new HashSet<String>(c.getCount());
 
-                        final ContentValues[] rows = new ContentValues[c.getCount()];
+                        final ArrayList<ContentValues> shortcuts = new ArrayList<ContentValues>();
+                        final ArrayList<ContentValues> folders = new ArrayList<ContentValues>();
 
                         while (c.moveToNext()) {
                             final int itemType = c.getInt(itemTypeIndex);
@@ -1538,29 +1539,43 @@
                                 + c.getString(titleIndex) + "\": " + intentStr, true);
 
                             if (itemType != Favorites.ITEM_TYPE_FOLDER) {
+
+                                final Intent intent;
+                                final ComponentName cn;
+                                try {
+                                    intent = Intent.parseUri(intentStr, 0);
+                                } catch (URISyntaxException e) {
+                                    // bogus intent?
+                                    Launcher.addDumpLog(TAG,
+                                            "skipping invalid intent uri", true);
+                                    continue;
+                                }
+
+                                cn = intent.getComponent();
                                 if (TextUtils.isEmpty(intentStr)) {
                                     // no intent? no icon
                                     Launcher.addDumpLog(TAG, "skipping empty intent", true);
                                     continue;
-                                } else {
-                                    try {
-                                        // Canonicalize
-                                        final Intent intent = Intent.parseUri(intentStr, 0);
-                                        // the Play Store sets the package parameter, but Launcher
-                                        // does not, so we clear that out to keep them the same
-                                        intent.setPackage(null);
-                                        final String key = intent.toUri(0);
-                                        if (seenIntents.contains(key)) {
-                                            Launcher.addDumpLog(TAG, "skipping duplicate", true);
-                                            continue;
-                                        } else {
-                                            seenIntents.add(key);
-                                        }
-                                    } catch (URISyntaxException e) {
-                                        // bogus intent?
-                                        Launcher.addDumpLog(TAG,
-                                                "skipping invalid intent uri", true);
+                                } else if (cn != null &&
+                                        !LauncherModel.isValidPackageComponent(pm, cn)) {
+                                    // component no longer exists.
+                                    Launcher.addDumpLog(TAG, "skipping item whose component " +
+                                            "no longer exists.", true);
+                                    continue;
+                                } else if (container ==
+                                        LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                                    // Dedupe icons directly on the workspace
+
+                                    // Canonicalize
+                                    // the Play Store sets the package parameter, but Launcher
+                                    // does not, so we clear that out to keep them the same
+                                    intent.setPackage(null);
+                                    final String key = intent.toUri(0);
+                                    if (seenIntents.contains(key)) {
+                                        Launcher.addDumpLog(TAG, "skipping duplicate", true);
                                         continue;
+                                    } else {
+                                        seenIntents.add(key);
                                     }
                                 }
                             }
@@ -1583,7 +1598,8 @@
                                     c.getInt(displayModeIndex));
 
                             if (container == LauncherSettings.Favorites.CONTAINER_HOTSEAT
-                                    && screen >= hotseatWidth) {
+                                    && (screen >= hotseatWidth ||
+                                        screen == grid.hotseatAllAppsRank)) {
                                 // no room for you in the hotseat? it's off to the desktop with you
                                 container = Favorites.CONTAINER_DESKTOP;
                             }
@@ -1594,32 +1610,53 @@
                                 values.put(LauncherSettings.Favorites.CELLX, cellX);
                                 values.put(LauncherSettings.Favorites.CELLY, cellY);
                             } else {
-                                values.put(LauncherSettings.Favorites.SCREEN, curScreen);
-                                values.put(LauncherSettings.Favorites.CELLX, curX);
-                                values.put(LauncherSettings.Favorites.CELLY, curY);
-                                curX = (curX + 1) % width;
-                                if (curX == 0) {
-                                    curY = (curY + 1);
-                                }
-                                // Leave the last row of icons blank on screen 0
-                                if (curScreen == 0 && curY == height - 1 || curY == height) {
-                                    curScreen = (int) generateNewScreenId();
-                                    curY = 0;
-                                }
+                                // For items contained directly on one of the workspace screen,
+                                // we'll determine their location (screen, x, y) in a second pass.
                             }
 
                             values.put(LauncherSettings.Favorites.CONTAINER, container);
 
-                            rows[i++] = values;
+                            if (itemType != Favorites.ITEM_TYPE_FOLDER) {
+                                shortcuts.add(values);
+                            } else {
+                                folders.add(values);
+                            }
                         }
 
-                        if (i > 0) {
+                        final ArrayList<ContentValues> allItems = new ArrayList<ContentValues>();
+                        // Folders first
+                        allItems.addAll(folders);
+                        // Then shortcuts
+                        allItems.addAll(shortcuts);
+
+                        // Layout all the folders
+                        for (ContentValues values: allItems) {
+                            if (values.getAsInteger(LauncherSettings.Favorites.CONTAINER) !=
+                                    LauncherSettings.Favorites.CONTAINER_DESKTOP) {
+                                // Hotseat items and folder items have already had their
+                                // location information set. Nothing to be done here.
+                                continue;
+                            }
+                            values.put(LauncherSettings.Favorites.SCREEN, curScreen);
+                            values.put(LauncherSettings.Favorites.CELLX, curX);
+                            values.put(LauncherSettings.Favorites.CELLY, curY);
+                            curX = (curX + 1) % width;
+                            if (curX == 0) {
+                                curY = (curY + 1);
+                            }
+                            // Leave the last row of icons blank on every screen
+                            if (curY == height - 1) {
+                                curScreen = (int) generateNewScreenId();
+                                curY = 0;
+                            }
+                        }
+
+                        if (allItems.size() > 0) {
                             db.beginTransaction();
                             try {
-                                final int N = rows.length;
-                                for (i = 0; i < N; i++) {
-                                    if (rows[i] == null) continue;
-                                    if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, rows[i])
+                                for (ContentValues row: allItems) {
+                                    if (row == null) continue;
+                                    if (dbInsertAndCheck(this, db, TABLE_FAVORITES, null, row)
                                             < 0) {
                                         return;
                                     } else {