Merge "Add optional flag to clear old preloaded workspace" into klp-dev
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f3ef6c8..288614f 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -26,7 +26,7 @@
     <permission
         android:name="com.android.launcher.permission.PRELOAD_WORKSPACE"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="system|signature" />
+        android:protectionLevel="signatureOrSystem" />
     <permission
         android:name="com.android.launcher.permission.INSTALL_SHORTCUT"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
@@ -48,7 +48,7 @@
     <permission
         android:name="com.android.launcher.permission.WRITE_SETTINGS"
         android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
-        android:protectionLevel="normal"
+        android:protectionLevel="signatureOrSystem"
         android:label="@string/permlab_write_settings"
         android:description="@string/permdesc_write_settings"/>
 
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 260410d..71da90c 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -73,10 +73,11 @@
     static final String TAG = "Launcher.Model";
 
     private static final int ITEMS_CHUNK = 6; // batch size for the workspace icons
-    private final boolean mAppsCanBeOnExternalStorage;
     private int mBatchSize; // 0 is all apps at once
     private int mAllAppsLoadDelay; // milliseconds between batches
 
+    private final boolean mAppsCanBeOnRemoveableStorage;
+
     private final LauncherApplication mApp;
     private final Object mLock = new Object();
     private DeferredHandler mHandler = new DeferredHandler();
@@ -169,7 +170,7 @@
     }
 
     LauncherModel(LauncherApplication app, IconCache iconCache) {
-        mAppsCanBeOnExternalStorage = !Environment.isExternalStorageEmulated();
+        mAppsCanBeOnRemoveableStorage = Environment.isExternalStorageRemovable();
         mApp = app;
         mBgAllAppsList = new AllAppsList(iconCache);
         mIconCache = iconCache;
@@ -817,15 +818,29 @@
             }
 
         } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
-            // First, schedule to add these apps back in.
+            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
             String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
-            enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages));
-            // Then, rebind everything.
-            startLoaderFromBackground();
+            if (!replacing) {
+                enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_ADD, packages));
+                if (mAppsCanBeOnRemoveableStorage) {
+                    // Only rebind if we support removable storage.  It catches the case where
+                    // apps on the external sd card need to be reloaded
+                    startLoaderFromBackground();
+                }
+            } else {
+                // If we are replacing then just update the packages in the list
+                enqueuePackageUpdated(new PackageUpdatedTask(PackageUpdatedTask.OP_UPDATE,
+                            packages));
+            }
         } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
-            String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
-            enqueuePackageUpdated(new PackageUpdatedTask(
-                        PackageUpdatedTask.OP_UNAVAILABLE, packages));
+            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
+            if (!replacing) {
+                String[] packages = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                enqueuePackageUpdated(new PackageUpdatedTask(
+                            PackageUpdatedTask.OP_UNAVAILABLE, packages));
+            }
+            // else, we are replacing the packages, so ignore this event and wait for
+            // EXTERNAL_APPLICATIONS_AVAILABLE to update the packages at that time
         } else if (Intent.ACTION_LOCALE_CHANGED.equals(action)) {
             // If we have changed locale we need to clear out the labels in all apps/workspace.
             forceReload();
@@ -2453,7 +2468,7 @@
     boolean queueIconToBeChecked(HashMap<Object, byte[]> cache, ShortcutInfo info, Cursor c,
             int iconIndex) {
         // If apps can't be on SD, don't even bother.
-        if (!mAppsCanBeOnExternalStorage) {
+        if (!mAppsCanBeOnRemoveableStorage) {
             return false;
         }
         // If this icon doesn't have a custom icon, check to see