Apps on sdcard: Add new broadcasts

Add new broadcasts ACTION_MEDIA_RESOURCES_AVAILABLE and
ACTION_MEDIA_RESOURCES_UNAVAILABLE that get broadcast by
PackageManagerService when sdcard gets mounted/unmounted
by MountService so that packages on sdcard get recognized by
various system services as being installed/available or
removed/unavailable by the system.
The broadcasts are sent before the actual package cleanup which includes
mounting/unmounting the packages and we force a gc right after so
that any lingering file references to resources on sdcard get
released.
diff --git a/services/java/com/android/server/BackupManagerService.java b/services/java/com/android/server/BackupManagerService.java
index ef184d2..0562c55 100644
--- a/services/java/com/android/server/BackupManagerService.java
+++ b/services/java/com/android/server/BackupManagerService.java
@@ -529,6 +529,11 @@
         filter.addAction(Intent.ACTION_PACKAGE_REMOVED);
         filter.addDataScheme("package");
         mContext.registerReceiver(mBroadcastReceiver, filter);
+        // Register for events related to sdcard installation.
+        IntentFilter sdFilter = new IntentFilter();
+        sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_AVAILABLE);
+        sdFilter.addAction(Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE);
+        mContext.registerReceiver(mBroadcastReceiver, sdFilter);
     }
 
     private void parseLeftoverJournals() {
@@ -665,35 +670,53 @@
         public void onReceive(Context context, Intent intent) {
             if (DEBUG) Log.d(TAG, "Received broadcast " + intent);
 
-            Uri uri = intent.getData();
-            if (uri == null) {
-                return;
-            }
-            String pkgName = uri.getSchemeSpecificPart();
-            if (pkgName == null) {
-                return;
-            }
-
             String action = intent.getAction();
-            if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
+            boolean replacing = false;
+            boolean added = false;
+            Bundle extras = intent.getExtras();
+            String pkgList[] = null;
+            if (Intent.ACTION_PACKAGE_ADDED.equals(action) ||
+                    Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
+                Uri uri = intent.getData();
+                if (uri == null) {
+                    return;
+                }
+                String pkgName = uri.getSchemeSpecificPart();
+                if (pkgName != null) {
+                    pkgList = new String[] { pkgName };
+                }
+                added = Intent.ACTION_PACKAGE_ADDED.equals(action);
+                replacing = extras.getBoolean(Intent.EXTRA_REPLACING, false);
+            } else if (Intent.ACTION_MEDIA_RESOURCES_AVAILABLE.equals(action)) {
+                added = true;
+                pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+            } else if (Intent.ACTION_MEDIA_RESOURCES_UNAVAILABLE.equals(action)) {
+                added = false;
+                pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+            }
+            if (pkgList == null || pkgList.length == 0) {
+                return;
+            }
+            if (added) {
                 synchronized (mBackupParticipants) {
-                    Bundle extras = intent.getExtras();
-                    if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
-                        // The package was just upgraded
-                        updatePackageParticipantsLocked(pkgName);
-                    } else {
-                        // The package was just added
-                        addPackageParticipantsLocked(pkgName);
+                    for (String pkgName : pkgList) {
+                        if (replacing) {
+                            // The package was just upgraded
+                            updatePackageParticipantsLocked(pkgName);
+                        } else {
+                            // The package was just added
+                            addPackageParticipantsLocked(pkgName);
+                        }
                     }
                 }
-            }
-            else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
-                Bundle extras = intent.getExtras();
-                if (extras != null && extras.getBoolean(Intent.EXTRA_REPLACING, false)) {
+            } else {
+                if (replacing) {
                     // The package is being updated.  We'll receive a PACKAGE_ADDED shortly.
                 } else {
                     synchronized (mBackupParticipants) {
-                        removePackageParticipantsLocked(pkgName);
+                        for (String pkgName : pkgList) {
+                            removePackageParticipantsLocked(pkgName);
+                        }
                     }
                 }
             }