Refactor the app updates so that it doesn't rely on the package name.

This will be needed for the upcoming change to update the icons with the
grayed out when the SD card goes away.
diff --git a/src/com/android/launcher2/AllApps2D.java b/src/com/android/launcher2/AllApps2D.java
index 1262880..0bb4ee9 100644
--- a/src/com/android/launcher2/AllApps2D.java
+++ b/src/com/android/launcher2/AllApps2D.java
@@ -279,7 +279,7 @@
         mAppsAdapter.notifyDataSetChanged();
     }
 
-    public void updateApps(String packageName, ArrayList<ApplicationInfo> list) {
+    public void updateApps(ArrayList<ApplicationInfo> list) {
         // Just remove and add, because they may need to be re-sorted.
         removeApps(list);
         addApps(list);
diff --git a/src/com/android/launcher2/AllApps3D.java b/src/com/android/launcher2/AllApps3D.java
index f571eff..c329b6c 100644
--- a/src/com/android/launcher2/AllApps3D.java
+++ b/src/com/android/launcher2/AllApps3D.java
@@ -772,7 +772,7 @@
         }
     }
     
-    public void updateApps(String packageName, ArrayList<ApplicationInfo> list) {
+    public void updateApps(ArrayList<ApplicationInfo> list) {
         // Just remove and add, because they may need to be re-sorted.
         removeApps(list);
         addApps(list);
diff --git a/src/com/android/launcher2/AllAppsView.java b/src/com/android/launcher2/AllAppsView.java
index 04f4040..a936f8b 100644
--- a/src/com/android/launcher2/AllAppsView.java
+++ b/src/com/android/launcher2/AllAppsView.java
@@ -39,7 +39,7 @@
 
     public void removeApps(ArrayList<ApplicationInfo> list);
 
-    public void updateApps(String packageName, ArrayList<ApplicationInfo> list);
+    public void updateApps(ArrayList<ApplicationInfo> list);
 
     public void dumpState();
 }
diff --git a/src/com/android/launcher2/Launcher.java b/src/com/android/launcher2/Launcher.java
index 903db1d..df2dd66 100644
--- a/src/com/android/launcher2/Launcher.java
+++ b/src/com/android/launcher2/Launcher.java
@@ -2055,7 +2055,7 @@
      *
      * Implementation of the method from LauncherModel.Callbacks.
      */
-    public void bindPackageAdded(ArrayList<ApplicationInfo> apps) {
+    public void bindAppsAdded(ArrayList<ApplicationInfo> apps) {
         removeDialog(DIALOG_CREATE_SHORTCUT);
         mAllAppsGrid.addApps(apps);
     }
@@ -2065,10 +2065,10 @@
      *
      * Implementation of the method from LauncherModel.Callbacks.
      */
-    public void bindPackageUpdated(String packageName, ArrayList<ApplicationInfo> apps) {
+    public void bindAppsUpdated(ArrayList<ApplicationInfo> apps) {
         removeDialog(DIALOG_CREATE_SHORTCUT);
-        mWorkspace.updateShortcutsForPackage(packageName);
-        mAllAppsGrid.updateApps(packageName, apps);
+        mWorkspace.updateShortcuts(apps);
+        mAllAppsGrid.updateApps(apps);
     }
 
     /**
@@ -2076,9 +2076,9 @@
      *
      * Implementation of the method from LauncherModel.Callbacks.
      */
-    public void bindPackageRemoved(String packageName, ArrayList<ApplicationInfo> apps) {
+    public void bindAppsRemoved(ArrayList<ApplicationInfo> apps) {
         removeDialog(DIALOG_CREATE_SHORTCUT);
-        mWorkspace.removeItemsForPackage(packageName);
+        mWorkspace.removeItems(apps);
         mAllAppsGrid.removeApps(apps);
     }
 
diff --git a/src/com/android/launcher2/LauncherApplication.java b/src/com/android/launcher2/LauncherApplication.java
index 183dbf5..be448a8 100644
--- a/src/com/android/launcher2/LauncherApplication.java
+++ b/src/com/android/launcher2/LauncherApplication.java
@@ -43,6 +43,10 @@
         filter.addAction(Intent.ACTION_PACKAGE_CHANGED);
         filter.addDataScheme("package");
         registerReceiver(mModel, filter);
+        filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
+        filter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
+        registerReceiver(mModel, filter);
 
         // Register for changes to the favorites
         ContentResolver resolver = getContentResolver();
diff --git a/src/com/android/launcher2/LauncherModel.java b/src/com/android/launcher2/LauncherModel.java
index 8790fd7..228b7a5 100644
--- a/src/com/android/launcher2/LauncherModel.java
+++ b/src/com/android/launcher2/LauncherModel.java
@@ -82,9 +82,9 @@
         public void finishBindingItems();
         public void bindAppWidget(LauncherAppWidgetInfo info);
         public void bindAllApplications(ArrayList<ApplicationInfo> apps);
-        public void bindPackageAdded(ArrayList<ApplicationInfo> apps);
-        public void bindPackageUpdated(String packageName, ArrayList<ApplicationInfo> apps);
-        public void bindPackageRemoved(String packageName, ArrayList<ApplicationInfo> apps);
+        public void bindAppsAdded(ArrayList<ApplicationInfo> apps);
+        public void bindAppsUpdated(ArrayList<ApplicationInfo> apps);
+        public void bindAppsRemoved(ArrayList<ApplicationInfo> apps);
     }
 
     LauncherModel(LauncherApplication app, IconCache iconCache) {
@@ -291,11 +291,11 @@
      * ACTION_PACKAGE_CHANGED.
      */
     public void onReceive(Context context, Intent intent) {
+        Log.d(TAG, "onReceive intent=" + intent);
+
         // Use the app as the context.
         context = mApp;
 
-        final String packageName = intent.getData().getSchemeSpecificPart();
-
         ArrayList<ApplicationInfo> added = null;
         ArrayList<ApplicationInfo> removed = null;
         ArrayList<ApplicationInfo> modified = null;
@@ -308,26 +308,48 @@
             }
 
             final String action = intent.getAction();
-            final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
 
-            if (packageName == null || packageName.length() == 0) {
-                // they sent us a bad intent
-                return;
-            }
+            if (Intent.ACTION_PACKAGE_CHANGED.equals(action)
+                    || Intent.ACTION_PACKAGE_REMOVED.equals(action)
+                    || Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+                final String packageName = intent.getData().getSchemeSpecificPart();
+                final boolean replacing = intent.getBooleanExtra(Intent.EXTRA_REPLACING, false);
 
-            if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
-                mAllAppsList.updatePackage(context, packageName);
-            } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
-                if (!replacing) {
-                    mAllAppsList.removePackage(packageName);
+                if (packageName == null || packageName.length() == 0) {
+                    // they sent us a bad intent
+                    return;
                 }
-                // else, we are replacing the package, so a PACKAGE_ADDED will be sent
-                // later, we will update the package at this time
-            } else {
-                if (!replacing) {
-                    mAllAppsList.addPackage(context, packageName);
-                } else {
+
+                if (Intent.ACTION_PACKAGE_CHANGED.equals(action)) {
                     mAllAppsList.updatePackage(context, packageName);
+                } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+                    if (!replacing) {
+                        mAllAppsList.removePackage(packageName);
+                    }
+                    // else, we are replacing the package, so a PACKAGE_ADDED will be sent
+                    // later, we will update the package at this time
+                } else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+                    if (!replacing) {
+                        mAllAppsList.addPackage(context, packageName);
+                    } else {
+                        mAllAppsList.updatePackage(context, packageName);
+                    }
+                }
+            } else {
+                if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
+                     String packages[] = intent.getStringArrayExtra(
+                             Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                     if (packages == null || packages.length == 0) {
+                         return;
+                     }
+                     Log.d(TAG, "they're back! " + packages);
+                } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE.equals(action)) {
+                     String packages[] = intent.getStringArrayExtra(
+                             Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                     if (packages == null || packages.length == 0) {
+                         return;
+                     }
+                     Log.d(TAG, "they're gone! " + packages);
                 }
             }
 
@@ -357,7 +379,7 @@
                 final ArrayList<ApplicationInfo> addedFinal = added;
                 mHandler.post(new Runnable() {
                     public void run() {
-                        callbacks.bindPackageAdded(addedFinal);
+                        callbacks.bindAppsAdded(addedFinal);
                     }
                 });
             }
@@ -365,7 +387,7 @@
                 final ArrayList<ApplicationInfo> modifiedFinal = modified;
                 mHandler.post(new Runnable() {
                     public void run() {
-                        callbacks.bindPackageUpdated(packageName, modifiedFinal);
+                        callbacks.bindAppsUpdated(modifiedFinal);
                     }
                 });
             }
@@ -373,7 +395,7 @@
                 final ArrayList<ApplicationInfo> removedFinal = removed;
                 mHandler.post(new Runnable() {
                     public void run() {
-                        callbacks.bindPackageRemoved(packageName, removedFinal);
+                        callbacks.bindAppsRemoved(removedFinal);
                     }
                 });
             }
diff --git a/src/com/android/launcher2/Workspace.java b/src/com/android/launcher2/Workspace.java
index d65a98c..cb4ba11 100644
--- a/src/com/android/launcher2/Workspace.java
+++ b/src/com/android/launcher2/Workspace.java
@@ -43,6 +43,7 @@
 import android.widget.TextView;
 
 import java.util.ArrayList;
+import java.util.HashSet;
 
 import com.android.launcher.R;
 
@@ -1223,11 +1224,17 @@
         mAllowLongPress = allowLongPress;
     }
 
-    void removeItemsForPackage(final String packageName) {
+    void removeItems(final ArrayList<ApplicationInfo> apps) {
         final int count = getChildCount();
         final PackageManager manager = getContext().getPackageManager();
         final AppWidgetManager widgets = AppWidgetManager.getInstance(getContext());
 
+        final HashSet<String> packageNames = new HashSet<String>();
+        final int appCount = apps.size();
+        for (int i = 0; i < appCount; i++) {
+            packageNames.add(apps.get(i).componentName.getPackageName());
+        }
+
         for (int i = 0; i < count; i++) {
             final CellLayout layout = (CellLayout) getChildAt(i);
 
@@ -1244,17 +1251,17 @@
         
                         if (tag instanceof ShortcutInfo) {
                             final ShortcutInfo info = (ShortcutInfo) tag;
-                            // We need to check for ACTION_MAIN otherwise getComponent() might
-                            // return null for some shortcuts (for instance, for shortcuts to
-                            // web pages.)
                             final Intent intent = info.intent;
                             final ComponentName name = intent.getComponent();
         
-                            if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
-                                    name != null && packageName.equals(name.getPackageName())) {
-                                // TODO: This should probably be done on a worker thread
-                                LauncherModel.deleteItemFromDatabase(mLauncher, info);
-                                childrenToRemove.add(view);
+                            if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
+                                for (String packageName: packageNames) {
+                                    if (packageName.equals(name.getPackageName())) {
+                                        // TODO: This should probably be done on a worker thread
+                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
+                                        childrenToRemove.add(view);
+                                    }
+                                }
                             }
                         } else if (tag instanceof UserFolderInfo) {
                             final UserFolderInfo info = (UserFolderInfo) tag;
@@ -1268,12 +1275,16 @@
                                 final Intent intent = appInfo.intent;
                                 final ComponentName name = intent.getComponent();
         
-                                if (Intent.ACTION_MAIN.equals(intent.getAction()) &&
-                                        name != null && packageName.equals(name.getPackageName())) {
-                                    toRemove.add(appInfo);
-                                    // TODO: This should probably be done on a worker thread
-                                    LauncherModel.deleteItemFromDatabase(mLauncher, appInfo);
-                                    removedFromFolder = true;
+                                if (Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
+                                    for (String packageName: packageNames) {
+                                        if (packageName.equals(name.getPackageName())) {
+                                            toRemove.add(appInfo);
+                                            // TODO: This should probably be done on a worker thread
+                                            LauncherModel.deleteItemFromDatabase(
+                                                    mLauncher, appInfo);
+                                            removedFromFolder = true;
+                                        }
+                                    }
                                 }
                             }
         
@@ -1288,21 +1299,27 @@
                             final ProviderInfo providerInfo = manager.resolveContentProvider(
                                     uri.getAuthority(), 0);
 
-                            if (providerInfo == null ||
-                                    packageName.equals(providerInfo.packageName)) {
-                                // TODO: This should probably be done on a worker thread
-                                LauncherModel.deleteItemFromDatabase(mLauncher, info);
-                                childrenToRemove.add(view);                        
+                            if (providerInfo == null) {
+                                for (String packageName: packageNames) {
+                                    if (packageName.equals(providerInfo.packageName)) {
+                                        // TODO: This should probably be done on a worker thread
+                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
+                                        childrenToRemove.add(view);                        
+                                    }
+                                }
                             }
                         } else if (tag instanceof LauncherAppWidgetInfo) {
                             final LauncherAppWidgetInfo info = (LauncherAppWidgetInfo) tag;
                             final AppWidgetProviderInfo provider =
                                     widgets.getAppWidgetInfo(info.appWidgetId);
-                            if (provider == null ||
-                                    packageName.equals(provider.provider.getPackageName())) {
-                                // TODO: This should probably be done on a worker thread
-                                LauncherModel.deleteItemFromDatabase(mLauncher, info);
-                                childrenToRemove.add(view);                                
+                            if (provider == null) {
+                                for (String packageName: packageNames) {
+                                    if (packageName.equals(provider.provider.getPackageName())) {
+                                        // TODO: This should probably be done on a worker thread
+                                        LauncherModel.deleteItemFromDatabase(mLauncher, info);
+                                        childrenToRemove.add(view);                                
+                                    }
+                                }
                             }
                         }
                     }
@@ -1325,7 +1342,7 @@
         }
     }
 
-    void updateShortcutsForPackage(String packageName) {
+    void updateShortcuts(ArrayList<ApplicationInfo> apps) {
         final PackageManager pm = mLauncher.getPackageManager();
 
         final int count = getChildCount();
@@ -1343,12 +1360,17 @@
                     final Intent intent = info.intent;
                     final ComponentName name = intent.getComponent();
                     if (info.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION &&
-                            Intent.ACTION_MAIN.equals(intent.getAction()) && name != null &&
-                            packageName.equals(name.getPackageName())) {
-
-                        info.setIcon(mIconCache.getIcon(info.intent));
-                        ((TextView) view).setCompoundDrawablesWithIntrinsicBounds(null,
-                                new FastBitmapDrawable(info.getIcon(mIconCache)), null, null);
+                            Intent.ACTION_MAIN.equals(intent.getAction()) && name != null) {
+                        final int appCount = apps.size();
+                        for (int k=0; k<appCount; k++) {
+                            ApplicationInfo app = apps.get(k);
+                            if (app.componentName.equals(name)) {
+                                info.setIcon(mIconCache.getIcon(info.intent));
+                                ((TextView)view).setCompoundDrawablesWithIntrinsicBounds(null,
+                                        new FastBitmapDrawable(info.getIcon(mIconCache)),
+                                        null, null);
+                                }
+                        }
                     }
                 }
             }