Merge "Fixing issue where items that were not yet added were not removed from the db. (Bug 6428418)" into jb-dev
diff --git a/res/values-ms/strings.xml b/res/values-ms/strings.xml
index a66c882..162138b 100644
--- a/res/values-ms/strings.xml
+++ b/res/values-ms/strings.xml
@@ -20,8 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="8424725141379931883">"Pelancar"</string>
-    <!-- no translation found for home (5921706419368316758) -->
-    <skip />
+    <string name="home" msgid="5921706419368316758">"Laman Utama"</string>
     <string name="uid_name" msgid="3371120195364560632">"Apl Teras Android"</string>
     <string name="folder_name" msgid="8551881338202938211"></string>
     <string name="chooser_wallpaper" msgid="6063168087625352235">"Pilih kertas dinding dari"</string>
diff --git a/res/values-zh-rCN/strings.xml b/res/values-zh-rCN/strings.xml
index 5043c22..00e60cd 100644
--- a/res/values-zh-rCN/strings.xml
+++ b/res/values-zh-rCN/strings.xml
@@ -20,8 +20,7 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="application_name" msgid="8424725141379931883">"启动器"</string>
-    <!-- no translation found for home (5921706419368316758) -->
-    <skip />
+    <string name="home" msgid="5921706419368316758">"主屏幕"</string>
     <string name="uid_name" msgid="3371120195364560632">"Android 核心应用"</string>
     <string name="folder_name" msgid="8551881338202938211"></string>
     <string name="chooser_wallpaper" msgid="6063168087625352235">"选择壁纸来源"</string>
diff --git a/src/com/android/launcher2/InstallShortcutReceiver.java b/src/com/android/launcher2/InstallShortcutReceiver.java
index 66b3f5f..6d91602 100644
--- a/src/com/android/launcher2/InstallShortcutReceiver.java
+++ b/src/com/android/launcher2/InstallShortcutReceiver.java
@@ -28,6 +28,7 @@
 
 import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.Set;
 
 public class InstallShortcutReceiver extends BroadcastReceiver {
@@ -47,16 +48,33 @@
     public static final String SHORTCUT_MIMETYPE =
             "com.android.launcher/shortcut";
 
-    private final int[] mCoordinates = new int[2];
+    // The set of shortcuts that are pending install
+    private static ArrayList<PendingInstallShortcutInfo> mInstallQueue =
+            new ArrayList<PendingInstallShortcutInfo>();
+
+    // Determines whether to defer installing shortcuts immediately until
+    // processAllPendingInstalls() is called.
+    private static boolean mUseInstallQueue = false;
+
+    private static class PendingInstallShortcutInfo {
+        Intent data;
+        Intent launchIntent;
+        String name;
+
+        public PendingInstallShortcutInfo(Intent rawData, String shortcutName,
+                Intent shortcutIntent) {
+            data = rawData;
+            name = shortcutName;
+            launchIntent = shortcutIntent;
+        }
+    }
 
     public void onReceive(Context context, Intent data) {
         if (!ACTION_INSTALL_SHORTCUT.equals(data.getAction())) {
             return;
         }
-        String spKey = LauncherApplication.getSharedPreferencesKey();
-        SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
 
-        final Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
+        Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
         if (intent == null) {
             return;
         }
@@ -73,6 +91,36 @@
             }
         }
 
+        PendingInstallShortcutInfo info = new PendingInstallShortcutInfo(data, name, intent);
+        if (mUseInstallQueue) {
+            mInstallQueue.add(info);
+        } else {
+            processInstallShortcut(context, info);
+        }
+    }
+
+    static void enableInstallQueue() {
+        mUseInstallQueue = true;
+    }
+
+    static void disableAndFlushInstallQueue(Context context) {
+        mUseInstallQueue = false;
+        Iterator<PendingInstallShortcutInfo> iter = mInstallQueue.iterator();
+        while (iter.hasNext()) {
+            processInstallShortcut(context, iter.next());
+            iter.remove();
+        }
+    }
+
+    private static void processInstallShortcut(Context context,
+            PendingInstallShortcutInfo pendingInfo) {
+        String spKey = LauncherApplication.getSharedPreferencesKey();
+        SharedPreferences sp = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
+
+        final Intent data = pendingInfo.data;
+        final Intent intent = pendingInfo.launchIntent;
+        final String name = pendingInfo.name;
+
         // Lock on the app so that we don't try and get the items while apps are being added
         LauncherApplication app = (LauncherApplication) context.getApplicationContext();
         final int[] result = {INSTALL_SHORTCUT_SUCCESSFUL};
@@ -106,10 +154,11 @@
         }
     }
 
-    private boolean installShortcut(Context context, Intent data, ArrayList<ItemInfo> items,
+    private static boolean installShortcut(Context context, Intent data, ArrayList<ItemInfo> items,
             String name, Intent intent, final int screen, boolean shortcutExists,
             final SharedPreferences sharedPrefs, int[] result) {
-        if (findEmptyCell(context, items, mCoordinates, screen)) {
+        int[] tmpCoordinates = new int[2];
+        if (findEmptyCell(context, items, tmpCoordinates, screen)) {
             if (intent != null) {
                 if (intent.getAction() == null) {
                     intent.setAction(Intent.ACTION_VIEW);
@@ -145,7 +194,7 @@
                     LauncherApplication app = (LauncherApplication) context.getApplicationContext();
                     ShortcutInfo info = app.getModel().addShortcut(context, data,
                             LauncherSettings.Favorites.CONTAINER_DESKTOP, screen,
-                            mCoordinates[0], mCoordinates[1], true);
+                            tmpCoordinates[0], tmpCoordinates[1], true);
                     if (info == null) {
                         return false;
                     }
diff --git a/src/com/android/launcher2/UninstallShortcutReceiver.java b/src/com/android/launcher2/UninstallShortcutReceiver.java
index 3f6de7c..84b1ad5 100644
--- a/src/com/android/launcher2/UninstallShortcutReceiver.java
+++ b/src/com/android/launcher2/UninstallShortcutReceiver.java
@@ -17,38 +17,83 @@
 package com.android.launcher2;
 
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.ContentResolver;
 import android.content.SharedPreferences;
 import android.database.Cursor;
 import android.net.Uri;
 import android.widget.Toast;
 
-import java.net.URISyntaxException;
-import java.util.HashSet;
-import java.util.Set;
-
 import com.android.launcher.R;
 
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
 public class UninstallShortcutReceiver extends BroadcastReceiver {
     private static final String ACTION_UNINSTALL_SHORTCUT =
             "com.android.launcher.action.UNINSTALL_SHORTCUT";
 
+    // The set of shortcuts that are pending uninstall
+    private static ArrayList<PendingUninstallShortcutInfo> mUninstallQueue =
+            new ArrayList<PendingUninstallShortcutInfo>();
+
+    // Determines whether to defer uninstalling shortcuts immediately until
+    // disableAndFlushUninstallQueue() is called.
+    private static boolean mUseUninstallQueue = false;
+
+    private static class PendingUninstallShortcutInfo {
+        Intent data;
+
+        public PendingUninstallShortcutInfo(Intent rawData) {
+            data = rawData;
+        }
+    }
+
     public void onReceive(Context context, Intent data) {
         if (!ACTION_UNINSTALL_SHORTCUT.equals(data.getAction())) {
             return;
         }
+
+        PendingUninstallShortcutInfo info = new PendingUninstallShortcutInfo(data);
+        if (mUseUninstallQueue) {
+            mUninstallQueue.add(info);
+        } else {
+            processUninstallShortcut(context, info);
+        }
+    }
+
+    static void enableUninstallQueue() {
+        mUseUninstallQueue = true;
+    }
+
+    static void disableAndFlushUninstallQueue(Context context) {
+        mUseUninstallQueue = false;
+        Iterator<PendingUninstallShortcutInfo> iter = mUninstallQueue.iterator();
+        while (iter.hasNext()) {
+            processUninstallShortcut(context, iter.next());
+            iter.remove();
+        }
+    }
+
+    private static void processUninstallShortcut(Context context,
+            PendingUninstallShortcutInfo pendingInfo) {
         String spKey = LauncherApplication.getSharedPreferencesKey();
         SharedPreferences sharedPrefs = context.getSharedPreferences(spKey, Context.MODE_PRIVATE);
 
+        final Intent data = pendingInfo.data;
+
         LauncherApplication app = (LauncherApplication) context.getApplicationContext();
         synchronized (app) {
             removeShortcut(context, data, sharedPrefs);
         }
     }
 
-    private void removeShortcut(Context context, Intent data, final SharedPreferences sharedPrefs) {
+    private static void removeShortcut(Context context, Intent data,
+            final SharedPreferences sharedPrefs) {
         Intent intent = data.getParcelableExtra(Intent.EXTRA_SHORTCUT_INTENT);
         String name = data.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
         boolean duplicate = data.getBooleanExtra(Launcher.EXTRA_SHORTCUT_DUPLICATE, true);
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index 86bc8f9..e946095 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -383,12 +383,20 @@
         mIsDragOccuring = true;
         updateChildrenLayersEnabled();
         mLauncher.lockScreenOrientation();
+
+        // Prevent any Un/InstallShortcutReceivers from updating the db while we are dragging
+        InstallShortcutReceiver.enableInstallQueue();
+        UninstallShortcutReceiver.enableUninstallQueue();
     }
 
     public void onDragEnd() {
         mIsDragOccuring = false;
         updateChildrenLayersEnabled();
         mLauncher.unlockScreenOrientation(false);
+
+        // Re-enable any Un/InstallShortcutReceiver and now process any queued items
+        InstallShortcutReceiver.disableAndFlushInstallQueue(getContext());
+        UninstallShortcutReceiver.disableAndFlushUninstallQueue(getContext());
     }
 
     /**